#!/bin/bash
{
	#////////////////////////////////////
	# DietPi-Config Script
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	#
	#////////////////////////////////////
	#
	# Info:
	# - Location: /boot/dietpi/dietpi-config
	#
	# Usage:
	# dietpi-config iMENUINDEX iEXITONBACK
	# - iMENUINDEX - Launch TARGETMENUID
	# - iEXITONBACK - 1=Exit DietPi-Config when going back to previous menu (applied to TARGETMENUINDEX 8 only!!)
	#////////////////////////////////////

	# Import DietPi-Globals --------------------------------------------------------------
	. /boot/dietpi/func/dietpi-globals
	readonly G_PROGRAM_NAME='DietPi-Config'
	G_CHECK_ROOT_USER
	G_CHECK_ROOTFS_RW
	G_INIT
	# Import DietPi-Globals --------------------------------------------------------------

	# Grab Inputs
	# - TARGETMENUID (valid positive interger)
	if disable_error=1 G_CHECK_VALIDINT "$1" 1; then

		TARGETMENUID=$1
		# Exit DietPi-Config instead of going back to previous menu?
		if [[ $2 == 1 ]]; then

			EXITONBACK=$2
			TEXT_MENU_BACK='Exit'

		fi

	fi

	#/////////////////////////////////////////////////////////////////////////////////////
	# Whiltail Info
	#/////////////////////////////////////////////////////////////////////////////////////
	Info_HW_OptionNotSupported(){ G_WHIP_MSG "This option is not available for $G_HW_MODEL_NAME"; }

	#/////////////////////////////////////////////////////////////////////////////////////
	# MENUS
	#/////////////////////////////////////////////////////////////////////////////////////
	TARGETMENUID=${TARGETMENUID:-0}
	EXITONBACK=${EXITONBACK:-0}
	TEXT_MENU_BACK=${TEXT_MENU_BACK:-Back}

	WHIP_SELECTION_PREVIOUS=
	REBOOT_REQUIRED=0

	# Interger min/max value holders
	MIN_VALUE=0
	MAX_VALUE=0

	# TARGETMENUID=0
	Menu_Main(){

		G_WHIP_MENU_ARRAY=(

			'1' ': Display Options'
			'2' ': Audio Options'

		)
		# Hide performance options on VM
		(( $G_HW_MODEL == 20 )) || G_WHIP_MENU_ARRAY+=('3' ': Performance Options')
		 G_WHIP_MENU_ARRAY+=(

			'4' ': Advanced Options'
			'5' ': Language/Regional Options'
			'6' ': Security Options'
			'7' ': Network Options: Adapters'
			'8' ': Network Options: Misc'
			'9' ': AutoStart Options'
			'10' ': Tools'

		)

		if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME"; then

			if (( $G_WHIP_RETURNED_VALUE == 1 )); then

				TARGETMENUID=1

			elif (( $G_WHIP_RETURNED_VALUE == 2 )); then

				TARGETMENUID=14

			elif (( $G_WHIP_RETURNED_VALUE == 3 )); then

				TARGETMENUID=4

			elif (( $G_WHIP_RETURNED_VALUE == 4 )); then

				TARGETMENUID=3

			elif (( $G_WHIP_RETURNED_VALUE == 5 )); then

				TARGETMENUID=7

			elif (( $G_WHIP_RETURNED_VALUE == 6 )); then

				TARGETMENUID=5

			elif (( $G_WHIP_RETURNED_VALUE == 7 )); then

				 TARGETMENUID=8

			elif (( $G_WHIP_RETURNED_VALUE == 8 )); then

				 TARGETMENUID=16

			elif (( $G_WHIP_RETURNED_VALUE == 9 )); then

				/boot/dietpi/dietpi-autostart

			elif (( $G_WHIP_RETURNED_VALUE == 10 )); then

				TARGETMENUID=11

			fi

		else

			Menu_Exit

		fi

	}

	# TARGETMENUID=-1, if we are to exit DietPi-Config
	Menu_Exit(){

		G_WHIP_SIZE_X_MAX=50
		if G_WHIP_YESNO "Exit $G_PROGRAM_NAME?"; then

			# Disable reboot when run from dietpi-software
			pgrep 'dietpi-software' > /dev/null && REBOOT_REQUIRED=0

			# Reboot required
			(( $REBOOT_REQUIRED )) && G_WHIP_YESNO 'A reboot is required to apply your new settings.\nWould you like to reboot now?' && reboot

			TARGETMENUID=-1

		# Return to DietPi-Config main menu
		elif (( ! $EXITONBACK )); then

			TARGETMENUID=0

		fi

	}

	Display_Rotation_Calc_XY_Invert(){

		# RPi only
		(( $G_HW_MODEL < 10 )) || { Info_HW_OptionNotSupported; return; }

		# 0=landscape 1=portrait
		local input=$1

		local framebuffer_x=$(grep -m1 '^[[:blank:]]*framebuffer_width=' /boot/config.txt || vcgencmd get_config framebuffer_width)
		framebuffer_x=${framebuffer_x#*=}; framebuffer_x=${framebuffer_x:-0}
		local framebuffer_y=$(grep -m1 '^[[:blank:]]*framebuffer_height=' /boot/config.txt || vcgencmd get_config framebuffer_height)
		framebuffer_y=${framebuffer_y#*=}; framebuffer_y=${framebuffer_y:-0}
		# 0/180 landscape
		if (( $input == 0 && $framebuffer_x < $framebuffer_y )); then

			G_CONFIG_INJECT 'framebuffer_width=' "framebuffer_width=$framebuffer_y" /boot/config.txt
			G_CONFIG_INJECT 'framebuffer_height=' "framebuffer_height=$framebuffer_x" /boot/config.txt

		# 90/270 portrait
		elif (( $input == 1 && $framebuffer_x > $framebuffer_y )); then

			G_CONFIG_INJECT 'framebuffer_width=' "framebuffer_width=$framebuffer_y" /boot/config.txt
			G_CONFIG_INJECT 'framebuffer_height=' "framebuffer_height=$framebuffer_x" /boot/config.txt

		fi

	}

	# TARGETMENUID=1
	Menu_DisplayOptions(){

		TARGETMENUID=0

		if (( $G_HW_MODEL == 21 )); then

			G_WHIP_MENU_ARRAY=('1' ': Display Driver')

		else

			G_WHIP_MENU_ARRAY=('1' ': Display Resolution')

			# On VM, do not show memory split or LCD panel menus
			if (( $G_HW_MODEL != 20 )); then

				G_WHIP_MENU_ARRAY+=('2' ': GPU/RAM Memory Split')
				local lcdpanel_text=$(sed -n '/^[[:blank:]]*CONFIG_LCDPANEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
				G_WHIP_MENU_ARRAY+=('3' ": LCD/OLED Panel addon: [${lcdpanel_text:=none}]")

			fi

		fi

		# Display brightness
		G_WHIP_MENU_ARRAY+=('16' ': Display Brightness')

		local xorg_dpi_current=$(sed -n '/^[[:blank:]]*SOFTWARE_XORG_DPI=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		G_WHIP_MENU_ARRAY+=('17' ": X.Org DPI: [${xorg_dpi_current:-N/A}]")

		(( $G_HW_MODEL == 20 )) || G_WHIP_MENU_ARRAY+=('14' ': LED Control')

		# RPi only
		if (( $G_HW_MODEL < 10 )); then

			# HDMI rotation
			local rotation_hdmi_current=$(sed -n '/^[[:blank:]]*display_hdmi_rotate=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('4' ": Rotation (HDMI)     : [${rotation_hdmi_current:=0}]")

			# LCD rotation
			local rotation_lcd_current=$(sed -n '/^[[:blank:]]*lcd_rotate=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('5' ": Rotation (LCD)      : [${rotation_lcd_current:=0}]")

			# Display overscan
			local overscan_disabled=$(grep -cm1 '^[[:blank:]]*disable_overscan=1' /boot/config.txt)
			local overscan_text='On'
			(( $overscan_disabled )) && overscan_text='Off'
			G_WHIP_MENU_ARRAY+=('6' ": Overscan            : [$overscan_text]")
			# - Overscan sizes
			if (( ! $overscan_disabled )); then

				local overscan_options=('overscan_left' 'overscan_right' 'overscan_top' 'overscan_bottom')
				local overscan_left=$(grep -m1 '^[[:blank:]]*overscan_left=' /boot/config.txt || vcgencmd get_config overscan_left); overscan_left=${overscan_left#*=}
				local overscan_right=$(grep -m1 '^[[:blank:]]*overscan_right=' /boot/config.txt || vcgencmd get_config overscan_right); overscan_right=${overscan_right#*=}
				local overscan_top=$(grep -m1 '^[[:blank:]]*overscan_top=' /boot/config.txt || vcgencmd get_config overscan_top); overscan_top=${overscan_top#*=}
				local overscan_bottom=$(grep -m1 '^[[:blank:]]*overscan_bottom=' /boot/config.txt || vcgencmd get_config overscan_bottom); overscan_bottom=${overscan_bottom#*=}
				G_WHIP_MENU_ARRAY+=('15' ": Overscan Compensation [L:${overscan_left:-N/A}] [R:${overscan_right:-N/A}] [T:${overscan_top:-N/A}] [B:${overscan_bottom:-N/A}]")

			fi

			# HDMI signal boost, RPi up to 3 only
			if (( $G_HW_MODEL < 4 )); then

				local hdmi_boost_current=$(grep -m1 '^[[:blank:]]*config_hdmi_boost=' /boot/config.txt || vcgencmd get_config config_hdmi_boost); hdmi_boost_current=${hdmi_boost_current#*=}
				G_WHIP_MENU_ARRAY+=('7'	": HDMI Boost          : [${hdmi_boost_current:-N/A}]")

			fi

			# RPi camera module
			local rpi_camera_module_enabled=$(grep -cm1 '^[[:blank:]]*start_x=1' /boot/config.txt)
			local rpi_camera_module_text='Off'
			(( $rpi_camera_module_enabled )) && rpi_camera_module_text='On'
			G_WHIP_MENU_ARRAY+=('8' ": RPi Camera          : [$rpi_camera_module_text]")

			# RPi camera LED
			local rpi_camera_led_disabled=$(grep -cm1 '^[[:blank:]]*disable_camera_led=1' /boot/config.txt)
			local rpi_camera_led_text='On'
			(( $rpi_camera_led_disabled )) && rpi_camera_led_text='Off'
			G_WHIP_MENU_ARRAY+=('9' ": RPi Camera LED      : [$rpi_camera_led_text]")

			# JustBoom IR Remote
			local justboom_ir_remote_text='Off'
			local justboom_ir_remote_enabled=0
			if [[ -f '/etc/systemd/system/justboom-ir-mpd.service' ]]; then

				justboom_ir_remote_text='On'
				justboom_ir_remote_enabled=1

			fi
			G_WHIP_MENU_ARRAY+=('11' ": JustBoom IR remote  : [$justboom_ir_remote_text]")

			# VC1 key
			local vc1_key_current=$(sed -n '/^[[:blank:]]*decode_WVC1=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('12' ": VC1 Key             : [${vc1_key_current:-none}]")

			# MPEG2 key
			local mpeg2_key_current=$(sed -n '/^[[:blank:]]*decode_MPG2=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('13' ": MPEG2 Key           : [${mpeg2_key_current:-none}]")

		# Odroids only
		elif (( $G_HW_MODEL < 13 )); then

			# Remote
			local odroid_remote_text='Off'
			local odroid_remote_enabled=0
			if [[ -f '/etc/systemd/system/odroid-remote.service' ]]; then

				odroid_remote_text='On'
				odroid_remote_enabled=1

			fi
			G_WHIP_MENU_ARRAY+=('10' ": Odroid remote : [$odroid_remote_text]")

		fi

		G_WHIP_DEFAULT_ITEM=$WHIP_SELECTION_PREVIOUS

		if G_WHIP_MENU 'Please select an option:'; then

			TARGETMENUID=1 # Return to this menu

			WHIP_SELECTION_PREVIOUS=$G_WHIP_RETURNED_VALUE

			if (( $G_WHIP_RETURNED_VALUE == 15 )); then

				for i in "${overscan_options[@]}"
				do
					G_WHIP_DEFAULT_ITEM=${!i}
					G_WHIP_INPUTBOX "Please enter a value (pixel count) for $i\n - E.g.: 16" || break

					G_CONFIG_INJECT "$i=" "$i=$G_WHIP_RETURNED_VALUE" /boot/config.txt
					REBOOT_REQUIRED=1
				done

			elif (( $G_WHIP_RETURNED_VALUE == 1 )); then

				TARGETMENUID=2

			elif (( $G_WHIP_RETURNED_VALUE == 3 )); then

				# RPi and Odroids only
				if (( $G_HW_MODEL < 20 )); then

					G_WHIP_MENU_ARRAY=('none' ': Uninstall all panels')
					G_WHIP_MENU_ARRAY+=('waveshare32' ': 320x240 panel with touch input')

					if (( $G_HW_MODEL < 10 )); then

						G_WHIP_MENU_ARRAY+=('esp01215e' ': Elecrow 1024x600 7" IPS HDMI panel with touch input')
						G_WHIP_MENU_ARRAY+=('allo-boss2-oled' ': Allo Boss2 DAC OLED display')

					else

						G_WHIP_MENU_ARRAY+=('odroid-lcd35' ': 480x320 panel with touch input')
						(( $G_HW_MODEL == 11 )) && G_WHIP_MENU_ARRAY+=('odroid-cloudshell' ': 320x240 panel')

					fi

					G_WHIP_DEFAULT_ITEM=$lcdpanel_text
					if G_WHIP_MENU 'Please select an option:'; then

						/boot/dietpi/func/dietpi-set_hardware lcdpanel "$G_WHIP_RETURNED_VALUE"
						REBOOT_REQUIRED=1

					fi

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 2 )); then

				if (( $G_HW_MODEL < 10 || $G_HW_MODEL == 12 )); then

					G_WHIP_MSG 'GPU/RAM Memory splits are pre-configured and applied during DietPi-Software setup.\n\nThe split value is optimized based on your software installs, however, feel free to tweak them.'
					TARGETMENUID=6

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 6 )); then

				# RPi only
				if (( $G_HW_MODEL < 10 )); then

					if (( $overscan_disabled )); then

						G_CONFIG_INJECT 'disable_overscan=' 'disable_overscan=0' /boot/config.txt

					else

						G_CONFIG_INJECT 'disable_overscan=' 'disable_overscan=1' /boot/config.txt
						for i in "${overscan_options[@]}"
						do
							sed -i "/^[[:blank:]]*$i=/c\#$i=0" /boot/config.txt
						done

					fi
					REBOOT_REQUIRED=1

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 7 )); then

				# RPi up to 3 only
				if (( $G_HW_MODEL < 4 )); then

					G_WHIP_MENU_ARRAY=(

						'0' ': Disabled'
						'2' ': RPi 1 A/B Default'
						'5' ': RPi 1+/2/3 Default'
						'6' ''
						'7' ': High (May increase stability)'
						'8' ''
						'9' ''
						'10' ''
						'11' ': Max (Not recommended)'

					)

					G_WHIP_DEFAULT_ITEM=$hdmi_boost_current
					if G_WHIP_MENU 'Please select a HDMI boost level.\n
A long (or insufficiently manufactured) cable may required a higher boost setting to achieve correct signal.'; then

						G_CONFIG_INJECT 'config_hdmi_boost=' "config_hdmi_boost=$G_WHIP_RETURNED_VALUE" /boot/config.txt
						REBOOT_REQUIRED=1

					fi

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 8 )); then

				# RPi only
				if (( $G_HW_MODEL < 10 )); then

					/boot/dietpi/func/dietpi-set_hardware rpi-camera $(( ! $rpi_camera_module_enabled )) && REBOOT_REQUIRED=1

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 9 )); then

				# RPi only
				if (( $G_HW_MODEL < 10 )); then

					G_CONFIG_INJECT 'disable_camera_led=' "disable_camera_led=$(( ! $rpi_camera_led_disabled ))" /boot/config.txt && REBOOT_REQUIRED=1

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 10 )); then

				if (( $odroid_remote_enabled )); then

					/boot/dietpi/func/dietpi-set_hardware remoteir none && REBOOT_REQUIRED=1

				elif G_WHIP_YESNO 'This will enable the IR modules, setup Lirc and the Odroid Remote for Odroid C1, C2 and XU4 Cloudshell.
\nNB: Other remotes can be configured by running "irrecord" and applying the codes to "/etc/lirc/lircd.conf"\n\nDo you wish to continue?'; then

					/boot/dietpi/func/dietpi-set_hardware remoteir odroid_remote && REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 11 )); then

				if (( $justboom_ir_remote_enabled )); then

					/boot/dietpi/func/dietpi-set_hardware remoteir none && REBOOT_REQUIRED=1

				elif G_WHIP_YESNO 'Got a JustBoom IR Remote? Excellent!
\nDietPi will enable the IR modules, setup Lirc and enable support for MPD controls by default:\n\nDo you wish to continue?'; then

					/boot/dietpi/func/dietpi-set_hardware remoteir justboom_ir_remote && REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 12 )); then

				G_WHIP_DEFAULT_ITEM=$vc1_key_current
				if G_WHIP_INPUTBOX 'Please enter your key for VC1:\n - EG: 0x00000000'; then

					G_CONFIG_INJECT 'decode_WVC1=' "decode_WVC1=$G_WHIP_RETURNED_VALUE" /boot/config.txt

					# https://github.com/MichaIng/DietPi/issues/1487
					local current_gpu_mem=$(sed -n '/^[[:blank:]]*gpu_mem_1024/{s/^[^=]*=//p;q}' /boot/config.txt)
					(( $current_gpu_mem < 128 )) && /boot/dietpi/func/dietpi-set_hardware gpumemsplit 128

					REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 13 )); then

				G_WHIP_DEFAULT_ITEM=$mpeg2_key_current
				if G_WHIP_INPUTBOX 'Please enter your key for MPEG2:\n - EG: 0x00000000'; then

					G_CONFIG_INJECT 'decode_MPG2=' "decode_MPG2=$G_WHIP_RETURNED_VALUE" /boot/config.txt

					# https://github.com/MichaIng/DietPi/issues/1487
					local current_gpu_mem=$(sed -n '/^[[:blank:]]*gpu_mem_1024/{s/^[^=]*=//p;q}' /boot/config.txt)
					(( $current_gpu_mem < 128 )) && /boot/dietpi/func/dietpi-set_hardware gpumemsplit 128

					REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 4 )); then

				G_WHIP_MENU_ARRAY=(

					'0' ': Disabled (default)'
					'1' ': 90 degrees'
					'2' ': 180 degrees'
					'3' ': 270 degrees'
					'0x10000' ': Horizontal flip'
					'0x20000' ': Vertical flip'

				)

				G_WHIP_DEFAULT_ITEM=$rotation_hdmi_current
				if G_WHIP_MENU "Please select an option:
\nNB: If you have the RPi touchscreen, please set this to 0 and use LCD rotation option."; then

					G_CONFIG_INJECT 'display_hdmi_rotate=' "display_hdmi_rotate=$G_WHIP_RETURNED_VALUE" /boot/config.txt

					# rotation 90/270 | invert x/y on FB (Y > X)
					if [[ $G_WHIP_RETURNED_VALUE == '1' || $G_WHIP_RETURNED_VALUE == '3' ]]; then

						Display_Rotation_Calc_XY_Invert 1

					# X > Y
					else

						Display_Rotation_Calc_XY_Invert 0

					fi
					REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 5 )); then

				G_WHIP_MENU_ARRAY=(

					'0' ': Disabled (default)'
					'2' ': 180 degrees'

				)

				G_WHIP_DEFAULT_ITEM=$rotation_lcd_current
				if G_WHIP_MENU 'Please select an option:\n\nNB: This option is for RPi touchscreen.'; then

					G_CONFIG_INJECT 'lcd_rotate=' "lcd_rotate=$G_WHIP_RETURNED_VALUE" /boot/config.txt && REBOOT_REQUIRED=1

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 14 )); then

				/boot/dietpi/dietpi-led_control

			elif (( $G_WHIP_RETURNED_VALUE == 16 )); then

				# Known FP's for setting brightness
				local afp_current_set_brightness=(

					'/sys/class/backlight/intel_backlight'
					'/sys/class/backlight/rpi_backlight'
					'/sys/class/backlight/lcd0'
					'/sys/class/backlight/backlight'

				)

				MIN_VALUE=0
				MAX_VALUE=255
				local fp_brightness current_brightness
				for fp_brightness in "${afp_current_set_brightness[@]}"
				do
					[[ -f $fp_brightness/brightness ]] || continue
					current_brightness=$(<"$fp_brightness/brightness")
					[[ -f $fp_brightness/max_brightness ]] && MAX_VALUE=$(<"$fp_brightness/max_brightness")
					break
				done

				if disable_error=1 G_CHECK_VALIDINT "$current_brightness"; then

					G_WHIP_DEFAULT_ITEM=$current_brightness
					if G_WHIP_INPUTBOX "Please enter a brightness value:\n - Min = $MIN_VALUE | Max = $MAX_VALUE" && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" "$MIN_VALUE" "$MAX_VALUE"; then

						echo "$G_WHIP_RETURNED_VALUE" > "$fp_brightness/brightness"

					fi

				else

					Info_HW_OptionNotSupported

				fi

			elif (( $G_WHIP_RETURNED_VALUE == 17 )); then

				G_WHIP_MENU_ARRAY=(

					'96' ': Default'
					'120' ": +25% larger"
					'144' ": +50% larger"
					'168' ": +75% larger"
					'192' ": +100% larger"

				)

				G_WHIP_DEFAULT_ITEM=$xorg_dpi_current
				if G_WHIP_MENU "Please select a DPI value for Xorg:
 - A higher value will make text and windows larger
 - Has no effect on local terminal (eg: no desktop installed)
 \nNB: Setting will only take effect, once system is restarted."; then

					G_CONFIG_INJECT 'SOFTWARE_XORG_DPI=' "SOFTWARE_XORG_DPI=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
					G_EXEC mkdir -p /etc/X11/Xsession.d
					echo "xrandr --dpi $G_WHIP_RETURNED_VALUE" > /etc/X11/Xsession.d/99-dietpi-dpi
					REBOOT_REQUIRED=1

				fi

			fi

		fi

	}

	Xorg_Configure(){

		if G_WHIP_YESNO 'Xorg Configuration:\nNB: This feature will only work if X server is NOT currently running.
\nPlease ensure:\n - No current X server (desktop) is running
\nIf a desktop is running, please set "dietpi-autostart" to "Console", reboot system, then rerun this option.
\nWould you like to continue?'; then

			G_EXEC Xorg -configure
			mv /root/xorg.conf.new /etc/X11/xorg.conf

		fi

	}

	# TARGETMENUID=2
	Menu_DisplayOptions_Driver_Resolution(){

		TARGETMENUID=1 # Return to Display Options menu

		# VM
		if (( $G_HW_MODEL == 20 )); then

			local current=$(sed -n '/^[[:blank:]]*GRUB_GFXMODE=/{s/^[^=]*=//p;q}' /etc/default/grub)
			[[ $current ]] || current='System default'

			G_WHIP_MENU_ARRAY=(

				'System default' ''
				'1600x1200' ''
				'1280x1024' ''
				'1152x864' ''
				'1024x768' ''
				'800x600' ''

			)

			G_WHIP_DEFAULT_ITEM=$current
			if G_WHIP_MENU "Please select a display resolution. Current: $current
\nNB: This only affects the virtual screen resolution, not the SSH session.
	You might need to increase the maximum guest screen resolution within your VM software."; then

				if [[ $G_WHIP_RETURNED_VALUE == 'System default' ]]; then

					sed -i 's/^[[:blank:]]*GRUB_GFXMODE=/#GRUB_GFXMODE=/' /etc/default/grub
					sed -i 's/^[[:blank:]]*GRUB_GFXPAYLOAD_LINUX=/#GRUB_GFXPAYLOAD_LINUX=/' /etc/default/grub

				else

					G_CONFIG_INJECT 'GRUB_GFXMODE=' "GRUB_GFXMODE=$G_WHIP_RETURNED_VALUE" /etc/default/grub
					G_CONFIG_INJECT 'GRUB_GFXPAYLOAD_LINUX=' 'GRUB_GFXPAYLOAD_LINUX=keep' /etc/default/grub 'GRUB_GFXMODE='

				fi

				update-grub

			fi

		# Native PC
		elif (( $G_HW_MODEL == 21 )); then

			local nvidia_installed=0
			local nvidia_text='Install GPU driver'
			if dpkg-query -s nvidia-driver &> /dev/null; then

				nvidia_installed=1
				nvidia_text='[Installed] Uninstall GPU driver'

			fi

			local intel_installed=0
			local intel_text='Install GPU driver'
			if dpkg-query -s xserver-xorg-video-intel &> /dev/null; then

				intel_installed=1
				intel_text='[Installed] Uninstall GPU driver'

			fi

			local amd_installed=0
			local amd_text='Install GPU driver'
			if dpkg-query -s xserver-xorg-video-amdgpu &> /dev/null; then

				amd_installed=1
				amd_text='[Installed] Uninstall GPU driver'

			fi

			G_WHIP_MENU_ARRAY=(

				'Nvidia' ": $nvidia_text"
				'Intel' ": $intel_text"
				'AMD' ": $amd_text"

			)

			if G_WHIP_MENU 'Please select an option:'; then

				TARGETMENUID=2

				if [[ $G_WHIP_RETURNED_VALUE == 'Nvidia' ]]; then

					if (( $nvidia_installed )); then

						/boot/dietpi/dietpi-software uninstall 151

					else

						/boot/dietpi/dietpi-software install 151

					fi
					REBOOT_REQUIRED=1

				elif [[ $G_WHIP_RETURNED_VALUE == 'Intel' ]]; then

					if (( $intel_installed )); then

						G_AGP i965-va-driver xserver-xorg-video-intel

					else

						G_AG_CHECK_INSTALL_PREREQ i965-va-driver xserver-xorg-video-intel libgl1-mesa-dri
						Xorg_Configure

					fi

				elif [[ $G_WHIP_RETURNED_VALUE == 'AMD' ]]; then

					if (( $amd_installed )); then

						G_AGP firmware-amd-graphics xserver-xorg-video-amdgpu

					else

						G_AG_CHECK_INSTALL_PREREQ firmware-amd-graphics xserver-xorg-video-amdgpu libgl1-mesa-dri
						Xorg_Configure

					fi

				fi

			fi

		# RPi
		elif (( $G_HW_MODEL < 10 )); then

			local framebuffer_x=$(grep -m1 '^[[:blank:]]*framebuffer_width=' /boot/config.txt || vcgencmd get_config framebuffer_width)
			framebuffer_x=${framebuffer_x#*=}; framebuffer_x=${framebuffer_x:-0}
			local framebuffer_y=$(grep -m1 '^[[:blank:]]*framebuffer_height=' /boot/config.txt || vcgencmd get_config framebuffer_height)
			framebuffer_y=${framebuffer_y#*=}; framebuffer_y=${framebuffer_y:-0}
			local current_value=$(sed -n '/^[[:blank:]]*dtoverlay=vc4-/{s/^[^=]*=//p;q}' /boot/config.txt) # OpenGL check 1st
			if [[ ! $current_value ]]; then

				# Framebuffer
				current_value="$framebuffer_x X $framebuffer_y"

				# Check for headless
				grep -q '^[[:blank:]]*AUTO_SETUP_HEADLESS=1' /boot/dietpi.txt && current_value='Headless'

			fi

			# RPi4 has its own full KMS overlay
			(( $G_HW_MODEL == 4 )) && G_WHIP_MENU_ARRAY=('vc4-kms-v3d-pi4' ': OpenGL | 1920 x 1080') || G_WHIP_MENU_ARRAY=('vc4-kms-v3d' ': OpenGL | 1920 x 1080')

			G_WHIP_MENU_ARRAY+=(

				'vc4-fkms-v3d' ': OpenGL | 1920 x 1080'
				'1080p' ': 1920 x 1080'
				'720p' ': 1280 x 720'
				'480p' ': 854 x 480'
				'RPi Touchscreen' ': 800 x 480'
				'PC1' ': 1024 x 768'
				'PC2' ': 800 x 640'
				'PC3' ': 640 x 480'
				'DietPi-Cloudshell' ': 320 x 240'
				'sdtv_mode=0' ': Composite NTSC'
				'sdtv_mode=1' ': Composite Japanese NTSC'
				'sdtv_mode=2' ': Composite PAL'
				'sdtv_mode=3' ': Composite Brazilian PAL'
				'Headless' ': Disables HDMI & Composite Output'

			)

			G_WHIP_DEFAULT_ITEM=$current_value
			if G_WHIP_MENU "Hardware: $G_HW_MODEL_NAME\nCurrent resolution: $current_value"; then

				REBOOT_REQUIRED=1

				TARGETMENUID=2 # Return to this menu

				# Enable headless if chosen, else always disable
				if [[ $G_WHIP_RETURNED_VALUE == 'Headless' ]]; then

					G_WHIP_YESNO 'Using the Headless option will:
 - Disable HDMI and composite output
 - Disable the framebuffer
 - Lower energy consumption by 0.1+ Watts
 - Improve RAM performance by 1-5% (VideoCore shares RAM bandwidth)
   Source: https://www.raspberrypi.org/forums/viewtopic.php?p=105008#p105008\n
Re-enabling HDMI requires a reboot. If you need emergency HDMI output, edit the following files on first partition of the SDcard from external system:
 - In config.txt, set "hdmi_ignore_hotplug=0" and comment/remove all (max_)framebuffer_(width/height) lines.
 - In dietpi.txt, set "AUTO_SETUP_HEADLESS=1".' || { REBOOT_REQUIRED=0; return; }

					/boot/dietpi/func/dietpi-set_hardware headless 1

				else

					/boot/dietpi/func/dietpi-set_hardware headless 0

				fi

				# Disable composite if not chosen
				if ! [[ $G_WHIP_RETURNED_VALUE == 'sdtv_mode'* ]]; then

					sed -i '/sdtv_mode=/c\#sdtv_mode=0' /boot/config.txt
					sed -i '/enable_tvout=/c\#enable_tvout=0' /boot/config.txt

				fi

				# Disable OpenGL if not chosen
				[[ $G_WHIP_RETURNED_VALUE == 'vc4-'* ]] || /boot/dietpi/func/dietpi-set_hardware rpi-opengl disable

				if [[ $G_WHIP_RETURNED_VALUE == 'vc4-'* ]]; then

					/boot/dietpi/func/dietpi-set_hardware rpi-opengl "$G_WHIP_RETURNED_VALUE"

				elif [[ $G_WHIP_RETURNED_VALUE != 'Headless' ]]; then

					case "$G_WHIP_RETURNED_VALUE" in

						'sdtv_mode'*)

							# Enable SDTV on RPi4, apply to all RPi to allow SDcard switch
							G_CONFIG_INJECT 'enable_tvout=' 'enable_tvout=1' /boot/config.txt
							G_CONFIG_INJECT 'sdtv_mode=' "$G_WHIP_RETURNED_VALUE" /boot/config.txt
							framebuffer_x=720
							framebuffer_y=576

						;;

						'DietPi-Cloudshell')

							framebuffer_x=320
							framebuffer_y=240

						;;

						'1080p')

							framebuffer_x=1920
							framebuffer_y=1080

						;;

						'720p')

							framebuffer_x=1280
							framebuffer_y=720

						;;

						'480p')

							framebuffer_x=854
							framebuffer_y=480

						;;

						'RPi Touchscreen')

							framebuffer_x=800
							framebuffer_y=480

						;;

						'PC1')

							framebuffer_x=1024
							framebuffer_y=768

						;;

						'PC2')

							framebuffer_x=800
							framebuffer_y=640

						;;

						'PC3')

							framebuffer_x=640
							framebuffer_y=480

						;;

					esac

					# Apply framebuffer size and ondemand Chromium resolution
					G_CONFIG_INJECT 'framebuffer_width=' "framebuffer_width=$framebuffer_x" /boot/config.txt
					G_CONFIG_INJECT 'framebuffer_height=' "framebuffer_height=$framebuffer_y" /boot/config.txt
					G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_X=' "SOFTWARE_CHROMIUM_RES_X=$framebuffer_x" /boot/dietpi.txt
					G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_Y=' "SOFTWARE_CHROMIUM_RES_Y=$framebuffer_y" /boot/dietpi.txt

				fi

			fi

		# Odroid XU3/XU4/HC1/HC2
		elif (( $G_HW_MODEL == 11 )); then

			# Get Current Values
			local current_resolution=$(grep -m1 'setenv videoconfig \"' /boot/boot.ini)
			if [[ $current_resolution == *'1920x1080'* ]]; then

				current_resolution='1080p'

			elif [[ $current_resolution == *'1280x720'* ]]; then

				current_resolution='720p'

			elif [[ $current_resolution == *'720x480'* ]]; then

				current_resolution='480p'

			fi

			G_WHIP_MENU_ARRAY=(

				'1920x1080' ': 1080p'
				'1280x720' ': 720p'
				'720x480' ': 480p'
				'1024x600' ': VU7+'

			)

			G_WHIP_DEFAULT_ITEM=$current_resolution
			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $current_resolution"; then

				REBOOT_REQUIRED=1

				TARGETMENUID=2 # Return to this menu

				# Always reset to HDMI
				sed -i '/setenv vout /c\setenv vout "hdmi"' /boot/boot.ini
				[[ $G_WHIP_RETURNED_VALUE == '1024x600' ]] && sed -i '/setenv vout /c\setenv vout "dvi"' /boot/boot.ini

				sed -i "/setenv videoconfig /c\setenv videoconfig \"drm_kms_helper.edid_firmware=edid/$G_WHIP_RETURNED_VALUE.bin\"" /boot/boot.ini

			fi

		# Odroid C2
		elif (( $G_HW_MODEL == 12 )); then

			# Get Current Values
			local current_resolution=$(mawk -F '"' '/setenv m "/{print $2;exit}' /boot/boot.ini | sed 's/p/p /')
			# - NB: also added space after xxxp, so its easier to read, and selects default item.

			G_WHIP_MENU_ARRAY=(

				'2160p 60hz' ': 4K (Recommended)'
				'2160p 50hz' ': 4K'
				'2160p 30hz' ': 4K'
				'2160p 25hz' ': 4K'
				'2160p 24hz' ': 4K'
				'1080p 60hz' ': 1080p (Recommended)'
				'1080p 50hz' ': 1080p'
				'1080p 24hz' ': 1080p'
				'720p 60hz' ': 720p (Recommended)'
				'720p 50hz' ': 720p'
				'480p 60hz' ': 480p'
				'1024x600p 60hz' ': VU7+'
				'1024x768p 60hz' ': 4:3'
				'800x600p 60hz' ': 4:3'

			)

			G_WHIP_DEFAULT_ITEM=$current_resolution
			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $current_resolution"; then

				[[ $current_resolution != "$G_WHIP_RETURNED_VALUE" ]] && REBOOT_REQUIRED=1

				# Always reset vga/dvi options
				sed -i '/^[[:blank:]]*setenv vout "dvi"/c\#setenv vout "dvi"' /boot/boot.ini
				sed -i '/^[[:blank:]]*setenv vout "vga"/c\#setenv vout "vga"' /boot/boot.ini

				# DVI / VU7+
				if [[ $G_WHIP_RETURNED_VALUE == '1024x600p 60hz' ]]; then

					# + DVI mode
					sed -i '/setenv vout "dvi"/c\setenv vout "dvi"' /boot/boot.ini

				fi

				# Remove the space from option
				local temp_string=${G_WHIP_RETURNED_VALUE//[[:blank:]]/}

				sed -i "/setenv m /c\setenv m \"$temp_string\"" /boot/boot.ini

				TARGETMENUID=2 # Return to this menu

			fi

		else

			Info_HW_OptionNotSupported

		fi

	}

	# TARGETMENUID=19
	Menu_AdvancedOptions_APT(){

		apt-config dump Dir::{Cache,State} > apt_conf
		local cache_enabled=$(grep -cm1 '^Dir::Cache::pkgcache "[^"]' apt_conf)
		local cache_in_ram=$(grep -cm1 '^Dir::Cache "/tmp' apt_conf)
		local lists_in_ram=$(grep -cm1 '^Dir::State "/tmp' apt_conf)
		local archives_in_ram=0
		(( $cache_in_ram )) && grep -q '^Dir::Cache::archives "[^/]' apt_conf || grep -q '^Dir::Cache::archives "/tmp' apt_conf && archives_in_ram=1

		local cache_text='On disk'
		(( $cache_in_ram )) && cache_text='In RAM'
		(( $cache_enabled )) || cache_text='Disabled'

		local lists_text='On disk'
		(( $lists_in_ram )) && lists_text='In RAM'

		local archives_text='On disk'
		(( $archives_in_ram )) && archives_text='In RAM'

		G_WHIP_MENU_ARRAY=(

			'Reset' ': Reset to system defaults'
			'APT cache' ": [$cache_text]"
			'APT lists' ": [$lists_text]"

		)
		(( $cache_in_ram )) && G_WHIP_MENU_ARRAY+=('APT archives' ": [$archives_text]")

		G_WHIP_BUTTON_CANCEL_TEXT='Back'
		if G_WHIP_MENU 'APT cache: Speeds up apt-cache search/show/... commands
 - 50-100 MiB size, gets fully rewritten on every APT update
\nAPT lists: Release files, one each distro and component
 - 50-100 MiB size, get individually rewritten if update available
\nAPT archives: Where APT downloads packages to for install
 - Can temporarily consume much space on large APT installs
 - Resets to disk if cache is moved to disk
\nPlease select an item to adjust:'; then

			[[ $G_WHIP_RETURNED_VALUE == 'Reset' ]] && { /boot/dietpi/func/dietpi-set_software apt-cache reset; return; }

			local item=$G_WHIP_RETURNED_VALUE
			G_WHIP_MENU_ARRAY=(

				'To disk' ": Move $item to disk (default)"
				'To RAM' ": Move $item to RAM"

			)
			[[ $item == 'APT cache' ]] && G_WHIP_MENU_ARRAY+=('Disable' ": Disable $item")

			local note=':'
			if [[ $item == 'APT lists' ]]; then

				note='.\n\nNB: Afterwards, you need to run "apt update" once before APT installs/upgrades can be done.
    When moving lists to RAM, this needs to be done once after each reboot unless CONFIG_CHECK_DIETPI_UPDATES=1 is set in /boot/dietpi.txt.
    DietPi scripts, however, automatically update APT lists on demand.'

			fi

			G_WHIP_MENU "Please select an option for $item$note" || return

			local option=${G_WHIP_RETURNED_VALUE#To }
			/boot/dietpi/func/dietpi-set_software apt-cache "${item#APT }" "${option,,}"

		else

			TARGETMENUID=3 # Return to Advanced Options

		fi

	}

	# TARGETMENUID=18
	Menu_AdvancedOptions_Serial_UART(){

		declare -A aSTATE=()
		G_WHIP_MENU_ARRAY=()

		(( $G_HW_MODEL < 10 )) && G_WHIP_MENU_ARRAY+=('' '●─ Toggle console ')
		for i in /dev/tty{S,AMA,SAC}[0-9]
		do
			[[ -e $i ]] || continue
			i=${i#/dev/}
			aSTATE[$i]='Off'
			systemctl -q is-active "serial-getty@$i" && aSTATE[$i]='On'
			G_WHIP_MENU_ARRAY+=("$i console" ": [${aSTATE[$i]}]")
		done

		# RPi special
		local rpi_text=
		if (( $G_HW_MODEL < 10 )); then

			local rpi_text='\n\nOn Raspberry Pi you can additionally enable or disable the primary UART device completely (requires reboot).'
			G_WHIP_MENU_ARRAY+=('' '●─ Toggle device ')

			# Onboard WiFi/BT: "enable_uart" toggles ttyS0 (mini UART), disabled by default
			if (( $G_HW_ONBOARD_WIFI )); then

				local rpi_uart='ttyS0 (mini UART)'
				local rpi_uart_state='Off'
				grep -q '^[[:blank:]]*enable_uart=1' /boot/config.txt && rpi_uart_state='On'

			# Nonboard WiFi/BT: "enable_uart" toggles ttyAMA0 (full UART). enabled by default
			else

				local rpi_uart='ttyAMA0 (full UART)'
				local rpi_uart_state='On'
				grep -q '^[[:blank:]]*enable_uart=0' /boot/config.txt && rpi_uart_state='Off'

			fi
			G_WHIP_MENU_ARRAY+=("$rpi_uart device" ": [$rpi_uart_state]")

		fi

		(( ${#G_WHIP_MENU_ARRAY[@]} > 2 )) || { G_WHIP_MSG 'No serial/UART devices have been found on your system.'; TARGETMENUID=3; return; }

		G_WHIP_BUTTON_CANCEL_TEXT='Back'
		if G_WHIP_MENU "Select an available serial/UART device to toggle a login console on it.$rpi_text"; then

			if [[ $G_WHIP_RETURNED_VALUE == *'device' ]]; then

				local toggle=1
				[[ $rpi_uart_state == 'On' ]] && toggle=0 && /boot/dietpi/func/dietpi-set_hardware serialconsole disable "${G_WHIP_RETURNED_VALUE%% *}"
				G_CONFIG_INJECT 'enable_uart=' "enable_uart=$toggle" /boot/config.txt && REBOOT_REQUIRED=1

			elif [[ $G_WHIP_RETURNED_VALUE == *'console' ]]; then

				local toggle='enable'
				[[ ${aSTATE[${G_WHIP_RETURNED_VALUE%% *}]} == 'On' ]] && toggle='disable'
				/boot/dietpi/func/dietpi-set_hardware serialconsole $toggle "${G_WHIP_RETURNED_VALUE%% *}"

			fi

		else

			TARGETMENUID=3 # Return to Advanced Options

		fi

	}

	# TARGETMENUID=3
	Menu_AdvancedOptions(){

		TARGETMENUID=0

		# Swap file
		local swap_size=$(free -m | mawk '/Swap:/ {print $2;exit}')
		local swap_location=$(sed -n '/^[[:blank:]]*AUTO_SETUP_SWAPFILE_LOCATION=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		local swap_size_text="$swap_size MB"
		(( $swap_size )) || swap_size_text='Off'
		G_WHIP_MENU_ARRAY=('Swap file' ": [$swap_size_text | $swap_location]")

		# APT cache
		G_WHIP_MENU_ARRAY+=('APT cache' ': Manage APT cache/info storage')

		# Time sync
		local ntpd_mode_current=$(sed -n '/^[[:blank:]]*CONFIG_NTP_MODE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		local ntpd_mode_text=''
		if (( $ntpd_mode_current == 0 )); then

			ntpd_mode_text='Custom'

		elif (( $ntpd_mode_current == 1 )); then

			ntpd_mode_text='Boot Only'

		elif (( $ntpd_mode_current == 2 )); then

			ntpd_mode_text='Boot + Daily'

		elif (( $ntpd_mode_current == 3 )); then

			ntpd_mode_text='Boot + Hourly'

		elif (( $ntpd_mode_current == 4 )); then

			ntpd_mode_text='Daemon + Drift'

		fi
		G_WHIP_MENU_ARRAY+=('Time sync mode' ": [$ntpd_mode_text]")

		# RTC clock: Only show option if a hwclock (connector) is available, otherwise fake-hwclock (default) is required anyway!
		if hwclock &> /dev/null; then

			local rtc_text='Hardware'
			command -v fake-hwclock &> /dev/null && rtc_text='Emulated'
			G_WHIP_MENU_ARRAY+=('RTC mode' ": [$rtc_text]")

		fi

		# Hide firmware update on RPi. This is done automatically with simple apt upgrade since raspberrypi-kernel is no meta-package.
		(( $G_HW_MODEL > 9 )) && G_WHIP_MENU_ARRAY+=('Update firmware' ": [Linux $(uname -r)]")
		# RPi4 EEPROM update: https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md
		if (( $G_HW_MODEL == 4 )); then

			if dpkg -s 'rpi-eeprom' &> /dev/null; then

				rpi-eeprom-update -m version_eeprom
				. ./version_eeprom
				rm version_eeprom
				G_WHIP_MENU_ARRAY+=('Update RPi4 EEPROM firmware' ": [Bootloader: ${BOOTLOADER_CURRENT:-N/A} | VL805: ${VL805_CURRENT:-N/A}]")

			else

				G_WHIP_MENU_ARRAY+=('Update RPi4 EEPROM firmware' ': Install rpi-eeprom APT package')

			fi

		fi

		# Serial/UART devices
		G_WHIP_MENU_ARRAY+=('Serial/UART' ': Manage available devices')

		# Bluetooth: Not for VM
		local bluetooth_state=1 bluetooth_state_text='On'
		[[ -f '/etc/modprobe.d/dietpi-disable_bluetooth.conf' ]] && bluetooth_state=0 bluetooth_state_text='Off'
		G_WHIP_MENU_ARRAY+=('Bluetooth' ": [$bluetooth_state_text]")

		# RPi specific
		if (( $G_HW_MODEL < 10 )); then

			# I2C state
			local rpi_i2c_enabled=$(grep -cm1 '^[[:blank:]]*dtparam=i2c_arm=on' /boot/config.txt)
			local rpi_i2c_text='Off'
			(( $rpi_i2c_enabled )) && rpi_i2c_text='On'
			G_WHIP_MENU_ARRAY+=('I2C state' ": [$rpi_i2c_text]")

			# I2C baudrate
			local rpi_i2c_baudrate=$(sed -n '/^[[:blank:]]*dtparam=i2c_arm_baudrate=/{s/^.*=//p;q}' /boot/config.txt)
			# - Allow commented/non-existent entry, using default value: https://github.com/raspberrypi/firmware/blob/d69aadedb7c146ba5d3b0b45a661e5669a9141c4/boot/overlays/README#L115-L116
			rpi_i2c_baudrate=$(( ${rpi_i2c_baudrate:-100000} / 1000 ))
			G_WHIP_MENU_ARRAY+=('I2C frequency' ": [$rpi_i2c_baudrate kHz]")

			# SPI state
			local rpi_spi_enabled=$(grep -cm1 '^[[:blank:]]*dtparam=spi=on' /boot/config.txt)
			local rpi_spi_text='Off'
			(( $rpi_spi_enabled )) && rpi_spi_text='On'
			G_WHIP_MENU_ARRAY+=('SPI state' ": [$rpi_spi_text]")

			# USB boot option: RPi3 only and not required for RPi3+: https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/msd.md
			if [[ $G_HW_MODEL == 3 && $G_HW_MODEL_NAME != *'+'* ]]; then

				local rpi3_usb_boot_bit_enabled=$(vcgencmd otp_dump | grep -cm1 '17:3020000a')
				local rpi3_usb_boot_bit_text='Off'
				(( $rpi3_usb_boot_bit_enabled )) && rpi3_usb_boot_bit_text='On'
				G_WHIP_MENU_ARRAY+=('USB boot support' ": [$rpi3_usb_boot_bit_text]")

			fi

		fi

		if G_WHIP_MENU 'Please select an option:'; then

			TARGETMENUID=3 # Return to this menu

			if [[ $G_WHIP_RETURNED_VALUE == 'Swap file' ]]; then

				G_WHIP_YESNO 'Swapfile control has been moved to DietPi-Drive_Manager, would you like to run the application now?
\nOnce finished, exit to resume DietPi-Config' && /boot/dietpi/dietpi-drive_manager

			elif [[ $G_WHIP_RETURNED_VALUE == 'APT cache' ]]; then

				TARGETMENUID=19

			elif [[ $G_WHIP_RETURNED_VALUE == 'RTC mode' ]]; then

				G_WHIP_MENU_ARRAY=(

					'Emulated' ': Use "fake-hwclock" to apply system clock on early boot'
					'Hardware' ': Device has an active hardware RTC, purge "fake-hwclock"'

				)

				G_WHIP_DEFAULT_ITEM=$rtc_text
				if G_WHIP_MENU 'Before network is available and network time sync can update the system clock, some implementation is required to do this on early boot stage.\n
RTC hardware clock:
 - Most x86 PCs and some SBCs have a hardware clock with battery attached, or, have a socket where it can optionally be attached to.
 - If active, this hardware clock will apply the correct system time during kernel boot stage.\n
fake-hwclock:
 - If no hardware RTC is available, the "fake-hwclock" package provides a service that saves the current system time on shutdown to a file, and, re-applies this stored time on early boot.
 - This means that the time is outdated if the system was shut down for a while, but without this implementation the system time would be 01/01/1970 until network time sync corrects it.\n
Please choose whether your device have an active RTC or requires "fake-hwclock":'; then

					if [[ $G_WHIP_RETURNED_VALUE == 'Emulated' ]]; then

						G_AGI fake-hwclock
						G_EXEC systemctl enable --now fake-hwclock

					else

						G_AGP fake-hwclock

					fi

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'Time sync mode' ]]; then

				G_WHIP_MENU_ARRAY=(

					'0' ': Custom'
					'1' ': Boot Only'
					'2' ': Boot + Daily (Recommended)'
					'3' ': Boot + Hourly'
					'4' ': Daemon + Drift'

				)

				G_WHIP_DEFAULT_ITEM=$ntpd_mode_current
				if G_WHIP_MENU 'Here you can adjust the frequency of network time syncs.\n
 - Modes 1-3:\nDietPi will launch systemd-timesyncd as a program, rather than a daemon. Once the time has been updated on your system, timesyncd will exit to reduce resource usage.\n
 - Mode 4:\nsystemd-timesyncd will run as a background daemon/service. Differences in time will be gradually adjusted over time, rather than instantly.\n
 - Mode 0:\nIf you use a custom time sync method, e.g. the NTP package for high precision demand, select custom mode to avoid systemd-timesyncd interference.'; then

					/boot/dietpi/func/dietpi-set_software ntpd-mode "$G_WHIP_RETURNED_VALUE"
					# Run time sync only, if not currently running, to avoid concurrent execution if dietpi-config was called from DietPi-Run_NTPD error handler
					# - Run non-interactively to avoid its internal error handler allowing to open a concurrent dietpi-config instance
					pgrep -cif /dietpi/func/run_ntpd > /dev/null || G_INTERACTIVE=0 MAX_LOOPS_CHECK=10 /boot/dietpi/func/run_ntpd 1

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'Update firmware' ]]; then

				local old_firmware=$(ls /lib/modules/)

				# Pine A64: Non-ARMbian only
				if [[ $G_HW_MODEL == 40 && -f '/usr/local/sbin/pine64_update_uboot.sh' && -f '/usr/local/sbin/pine64_update_kernel.sh' ]]; then

					if G_WHIP_YESNO "Would you like to update the firmware/kernel for $G_HW_MODEL_NAME?
 - This will run longsleep's update scripts to update the U-Boot and kernel."; then

						/usr/local/sbin/pine64_update_uboot.sh
						/usr/local/sbin/pine64_update_kernel.sh

					fi

				# G_AGDUG based (not all devices support this)
				elif G_WHIP_YESNO "Would you like to update the firmware/kernel for $G_HW_MODEL_NAME?
 - This will run G_AGDUG, a wrapper for 'apt-get dist-upgrade'\n - Most (but not all) devices allow APT based firmware updates
 \nNB: If requested to overwrite the current kernel, press TAB and then ENTER (to confirm)."; then

					G_AGUP
					G_AGDUG

				fi

				# Reboot required only, if firmware got actually updated
				[[ $old_firmware != $(ls /lib/modules/) ]] && REBOOT_REQUIRED=1

			elif [[ $G_WHIP_RETURNED_VALUE == 'Update RPi4 EEPROM firmware' ]]; then

				G_WHIP_YESNO '[ INFO ] EEPROM firmware update
\nThis will, if required, install or upgrade the rpi-eeprom APT package and update bootloader and VL805 USB firmware on the RPi4 EEPROM.
Further information: https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md
\nDo you want to continue?' || return
				/boot/dietpi/func/dietpi-set_hardware rpi-eeprom

			elif [[ $G_WHIP_RETURNED_VALUE == 'I2C state' ]]; then

				/boot/dietpi/func/dietpi-set_hardware i2c $(( ! $rpi_i2c_enabled )) && REBOOT_REQUIRED=1

			elif [[ $G_WHIP_RETURNED_VALUE == 'I2C frequency' ]]; then

				# Remove kHz from current
				G_WHIP_DEFAULT_ITEM=$rpi_i2c_baudrate
				if G_WHIP_INPUTBOX 'Please enter the required I2C baudrate frequency (kHz).' && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 0; then

					/boot/dietpi/func/dietpi-set_hardware i2c "$G_WHIP_RETURNED_VALUE" && REBOOT_REQUIRED=1

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'SPI state' ]]; then

				/boot/dietpi/func/dietpi-set_hardware spi $(( ! $rpi_spi_enabled )) && REBOOT_REQUIRED=1

			elif [[ $G_WHIP_RETURNED_VALUE == 'Serial/UART' ]]; then

				TARGETMENUID=18

			elif [[ $G_WHIP_RETURNED_VALUE == 'Bluetooth' ]]; then

				/boot/dietpi/func/dietpi-set_hardware bluetooth $(( ! $bluetooth_state ))
				# On RPi, when enabling onboard Bluetooth, a reboot is required to have the device tree changes taking effect.
				(( $bluetooth_state || G_HW_MODEL > 9 )) || (( ! $G_HW_ONBOARD_WIFI )) || REBOOT_REQUIRED=1

			elif [[ $G_WHIP_RETURNED_VALUE == 'USB boot support' && $rpi3_usb_boot_bit_enabled == 0 ]] &&
				G_WHIP_YESNO 'The following will enable the RPi 3 to boot from USB mass storage devices. A hardware bit "17:3020000a" is set on next boot to enable the feature.
\nNB:\n - Not all USB mass storage devices are supported.\n - The hardware bit which enables this setting is non-reversible.
\nDo you wish to enable USB mass storage boot support?'; then

				/boot/dietpi/func/dietpi-set_hardware rpi3_usb_boot enable && REBOOT_REQUIRED=1

			fi

		fi

	}

	# TARGETMENUID=4
	Menu_PerformanceOptions(){

		TARGETMENUID=0

		# All devices
		local current_cpu_governor='N/A'
		local fp_current_cpu_governor='/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
		[[ -f $fp_current_cpu_governor ]] && current_cpu_governor=$(<$fp_current_cpu_governor)

		local frequency_min_cpu_governor='N/A'
		local fp_frequency_min_cpu_governor='/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'
		[[ -f $fp_frequency_min_cpu_governor ]] && frequency_min_cpu_governor=$(( $(<$fp_frequency_min_cpu_governor) / 1000 ))

		local frequency_max_cpu_governor='N/A'
		local fp_frequency_max_cpu_governor='/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq'
		[[ -f $fp_frequency_max_cpu_governor ]] && frequency_max_cpu_governor=$(( $(<$fp_frequency_max_cpu_governor) / 1000 ))

		local cpu_temp=$(G_OBTAIN_CPU_TEMP)
		local cpu_temp_f='N/A'
		if disable_error=1 G_CHECK_VALIDINT "$cpu_temp"; then

			cpu_temp_f="$(( $cpu_temp * 9/5 + 32 ))'f"
			cpu_temp+="'c"

		fi

		local memory_total=$(mawk '/MemTotal:/{printf "%.0f",$2/1024;exit}' /proc/meminfo)
		local memory_free=$(mawk '/MemAvailable:/{printf "%.0f",$2/1024;exit}' /proc/meminfo)
		# Fallback for Linux pre-v4: https://github.com/MichaIng/DietPi/issues/3799
		(( $memory_free )) || memory_free=$(mawk '/MemFree:/{printf "%.0f",$2/1024;exit}' /proc/meminfo)
		local memory_usage=$(( $memory_total - $memory_free ))

		# Create Menu List for Whiptail
		# - this will list the menu options available for each device.
		G_WHIP_MENU_ARRAY=()

		# RPi: Overclocking
		(( $G_HW_MODEL < 10 )) && G_WHIP_MENU_ARRAY+=('Overclocking' ': Set Profile')

		# CPU GOV
		G_WHIP_MENU_ARRAY+=('CPU Governor' ": [$current_cpu_governor]")

		# ondemand/conservative/interactive throttle up menu
		if [[ $current_cpu_governor == 'ondemand' || $current_cpu_governor == 'conservative' || $current_cpu_governor == 'interactive' ]]; then

			local current_cpu_throttle_up=$(sed -n '/^[[:blank:]]*CONFIG_CPU_USAGE_THROTTLE_UP=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			G_WHIP_MENU_ARRAY+=('CPU Throttle Up' ": [${current_cpu_throttle_up}%]")

		fi

		# Ondemand extras
		if [[ $current_cpu_governor == 'ondemand' ]]; then

			local current_cpu_sample_rate=$(( $(sed -n '/^[[:blank:]]*CONFIG_CPU_ONDEMAND_SAMPLE_RATE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) / 1000 )) # Convert to ms
			G_WHIP_MENU_ARRAY+=('Ondemand Sample Rate' ": [${current_cpu_sample_rate}ms]")

			local current_cpu_down_factor=$(sed -n '/^[[:blank:]]*CONFIG_CPU_ONDEMAND_SAMPLE_DOWNFACTOR=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			local current_cpu_down_factor_ms=$(( $current_cpu_down_factor * $current_cpu_sample_rate ))
			G_WHIP_MENU_ARRAY+=('Ondemand Down Factor' ": [$current_cpu_down_factor (${current_cpu_down_factor_ms}ms)]")

		fi

		# Intel boost option (eg: i5-6200U, disables 2.9GHz mode, limits to 2.3GHz)
		local intel_boost_disabled=0
		local intel_boost_text='Enabled'
		if grep -qi 'genuineintel' /proc/cpuinfo; then

			intel_boost_disabled=$(sed -n '/^[[:blank:]]*CONFIG_CPU_DISABLE_TURBO=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			(( $intel_boost_disabled )) && intel_boost_text='Disabled'
			G_WHIP_MENU_ARRAY+=('Intel Turbo/Boost' ": [$intel_boost_text]")

		fi

		# RPi extras
		if (( $G_HW_MODEL < 10 )); then

			local temp_limit=$(sed -n '/^[[:blank:]]*temp_limit=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('ARM Temp Limit' ": [${temp_limit:=85}'c]")

			local arm_freq_min=$(sed -n '/^[[:blank:]]*arm_freq_min=/{s/^[^=]*=//p;q}' /boot/config.txt)
			[[ $arm_freq_min ]] || { [[ $G_HW_MODEL == [01] ]] && arm_freq_min=700 || arm_freq_min=600; } # 700 on RPi1+Zero else 600
			G_WHIP_MENU_ARRAY+=('ARM Idle Frequency' ": [$arm_freq_min MHz]") # https://github.com/MichaIng/DietPi/issues/3690

			local initial_turbo=$(sed -n '/^[[:blank:]]*initial_turbo=/{s/^[^=]*=//p;q}' /boot/config.txt)
			G_WHIP_MENU_ARRAY+=('ARM Initial Turbo' ": [${initial_turbo:=0} seconds]")

		# Define CPU scaling frequency or percent
		# - Disabled on RPi since ondemand only jumps between lowest and highest by default. RPi user hence should use "ARM Idle Frequency" option + overclocking to set those two freqs.
		else

			local type_cpu_freq_info='MHz'
			# Intel
			[[ -f '/sys/devices/system/cpu/intel_pstate/max_perf_pct' ]] && type_cpu_freq_info='%'

			# User Scaling Max Freq limit
			local user_frequency_max_current=$(sed -n '/^[[:blank:]]*CONFIG_CPU_MAX_FREQ=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			local user_frequency_max_text="$user_frequency_max_current $type_cpu_freq_info"
			(( $user_frequency_max_current )) || user_frequency_max_text='Off'

			# User Scaling Min Freq limit
			local user_frequency_min_current=$(sed -n '/^[[:blank:]]*CONFIG_CPU_MIN_FREQ=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			local user_frequency_min_text="$user_frequency_min_current $type_cpu_freq_info"
			(( $user_frequency_min_current )) || user_frequency_min_text='Off'

			G_WHIP_MENU_ARRAY+=('CPU Frequency Limits' ": Max = [$user_frequency_max_text] | Min = [$user_frequency_min_text]")

		fi

		if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCPU Temp: $cpu_temp : $cpu_temp_f\nRAM: $memory_total MiB | Used: $memory_usage MiB | Free: $memory_free MiB"; then

			TARGETMENUID=4 # Return to this menu

			case "$G_WHIP_RETURNED_VALUE" in

				'Intel Turbo/Boost')

					(( $intel_boost_disabled )) && intel_boost_disabled=0 || intel_boost_disabled=1
					G_CONFIG_INJECT 'CONFIG_CPU_DISABLE_TURBO=' "CONFIG_CPU_DISABLE_TURBO=$intel_boost_disabled" /boot/dietpi.txt
					/boot/dietpi/func/dietpi-set_cpu

				;;

				'Ondemand Down Factor')

					MIN_VALUE=1 MAX_VALUE=200
					G_WHIP_DEFAULT_ITEM=$current_cpu_down_factor
					if G_WHIP_INPUTBOX "After Ondemand throttles up, how long before the next sample to check if CPU clocks can be reduced.\n\n - This value * 'Ondemand Sample Rate' = total miliseconds\n - Lower values may help reduce power consumption, however, a 500-1000ms value is recommended to prevent excessive sampling.\n - Valid range: $MIN_VALUE - $MAX_VALUE\n
If unsure, set any value, 'Ondemand Down Factor' option on the next screen will list the calculated miliseconds." && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE $MAX_VALUE; then

						G_CONFIG_INJECT 'CONFIG_CPU_ONDEMAND_SAMPLE_DOWNFACTOR=' "CONFIG_CPU_ONDEMAND_SAMPLE_DOWNFACTOR=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
						/boot/dietpi/func/dietpi-set_cpu

					fi

				;;

				'Ondemand Sample Rate')

					local file=
					local afile=(

						'/sys/devices/system/cpu/cpufreq/ondemand/sampling_rate_min'
						'/sys/devices/system/cpu/cpufreq/ondemand/min_sampling_rate'
						'/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate_min'
						'/sys/devices/system/cpu/cpu0/cpufreq/ondemand/min_sampling_rate'

					)

					for i in "${afile[@]}"
					do
						[[ -f $i ]] && file=$i && break
					done

					if [[ $file ]]; then

						MIN_VALUE=$(( $(<"$file") / 1000 ))

					# Unable to find min value, hard set it
					else

						MIN_VALUE=20 # RPi is min 20ms, however, no way to currently detect min available values...

					fi

					MAX_VALUE=300
					G_WHIP_DEFAULT_ITEM=$current_cpu_sample_rate
					if G_WHIP_INPUTBOX "Please enter a sample rate in milliseconds, for Ondemand to check if it needs to increase CPU clocks.\nA lower value will make the system more responsive.
 - Valid range: $MIN_VALUE - $MAX_VALUE" && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE $MAX_VALUE; then

						G_CONFIG_INJECT 'CONFIG_CPU_ONDEMAND_SAMPLE_RATE=' "CONFIG_CPU_ONDEMAND_SAMPLE_RATE=$(( $G_WHIP_RETURNED_VALUE * 1000 ))" /boot/dietpi.txt
						/boot/dietpi/func/dietpi-set_cpu

					fi

				;;

				'CPU Frequency Limits')

					# Create /tmp/dietpi-available_cpu_freqs containing available scaling frequencies
					/boot/dietpi/dietpi-cpuinfo 2

					if [[ ! -f '/tmp/dietpi-available_cpu_freqs' ]]; then

						G_WHIP_MSG 'The processor and/or kernel, does not support this feature.\n\n(Info): Scaling_available_frequencies does not exist.'

					else

						# Map to array
						local available_frequency_array=()
						mapfile -t available_frequency_array < /tmp/dietpi-available_cpu_freqs
						rm /tmp/dietpi-available_cpu_freqs

						# Convert to MHz
						local division_factor=1000
						# Intel: Skip conversion
						[[ -f '/sys/devices/system/cpu/intel_pstate/max_perf_pct' ]] && division_factor=1

						local index=0 # 0=max | 1=min
						while (( $index < 2 ))
						do
							G_WHIP_MENU_ARRAY=()
							for i in "${available_frequency_array[@]}"
							do
								G_WHIP_MENU_ARRAY+=($(( $i / $division_factor )) "$type_cpu_freq_info")
							done
							G_WHIP_MENU_ARRAY+=('Disabled' ': Returns clocks to default')

							# MAX
							if (( $index == 0 )); then

								G_WHIP_DEFAULT_ITEM=$user_frequency_max_current
								G_WHIP_MENU "Limit the maximum frequency that your processor can reach.\nThis can be useful for lowering temperature and saving power.\n
Current setting: $user_frequency_max_text" && G_CONFIG_INJECT 'CONFIG_CPU_MAX_FREQ=' "CONFIG_CPU_MAX_FREQ=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt

							# MIN
							else

								G_WHIP_DEFAULT_ITEM=$user_frequency_min_current
								G_WHIP_MENU "Limit the minimum frequency that your processor can reach.\nThis can be useful for some timing critical stuff (eg. 1-wire below 480 Mhz won't work).\n
Current setting: $user_frequency_min_text" && G_CONFIG_INJECT 'CONFIG_CPU_MIN_FREQ=' "CONFIG_CPU_MIN_FREQ=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt

							fi

							((index++))
						done
						unset -v available_frequency_array

						/boot/dietpi/func/dietpi-set_cpu

					fi

				;;

				'Overclocking')

					TARGETMENUID=13

				;;

				'CPU Governor')

					local fp_governor='/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors'

					# Scaling govs not available (No Gavnor!)
					if [[ ! -f $fp_governor ]]; then

						G_WHIP_MSG 'Your processor, or kernel, does not support this feature.\n\n(Info): scaling_available_governors does not exist.'

					# Obtain available Govs. Setup their menu and description. (Yes Gavnor!)
					else

						local Description='CPU Governor: https://www.kernel.org/doc/html/latest/admin-guide/pm/cpufreq.html#generic-scaling-governors'
						G_WHIP_MENU_ARRAY=()
						if grep -qi 'schedutil' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('schedutil' ": Scales CPU frequency between $frequency_min_cpu_governor MHz and $frequency_max_cpu_governor MHz")
							Description+='\nSchedutil    | Dynamic CPU frequency based on CPU scheduler metrics (recommended on modern kernels)'

						fi
						if grep -qi 'ondemand' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('ondemand' ": Scales CPU frequency between $frequency_min_cpu_governor MHz and $frequency_max_cpu_governor MHz")
							Description+='\nOndemand     | Dynamic CPU frequency based on usage (recommended on older kernels)'

						fi
						if grep -qi 'interactive' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('interactive' ": Scales CPU frequency between $frequency_min_cpu_governor MHz and $frequency_max_cpu_governor MHz")
							Description+='\nInteractive  | Same as ondemand. Bias towards low latency, faster scaling'

						fi
						if grep -qi 'conservative' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('conservative' ": Scales CPU frequency between $frequency_min_cpu_governor MHz and $frequency_max_cpu_governor MHz")
							Description+='\nConservative | Same as ondemand. Bias towards powersaving, slower scaling'

						fi
						if grep -qi 'powersave' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('powersave' ": Limits CPU frequency to $frequency_min_cpu_governor MHz")
							Description+='\nPowersave    | Static. Reduces energy consumption, heat, performance'

						fi
						if grep -qi 'performance' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('performance' ": Forces CPU frequency to $frequency_max_cpu_governor MHz")
							Description+='\nPerformance  | Static. Increases energy consumption, heat, performance'

						fi
						if grep -qi 'userspace' $fp_governor; then

							G_WHIP_MENU_ARRAY+=('userspace' ": No-op governor, allows setting frequency manually")
							Description+='\nUserspace    | No-op. Governor does not touch CPU frequency at all'

						fi
						G_WHIP_DEFAULT_ITEM=$current_cpu_governor
						if G_WHIP_MENU "$Description"; then

							G_CONFIG_INJECT 'CONFIG_CPU_GOVERNOR=' "CONFIG_CPU_GOVERNOR=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
							/boot/dietpi/func/dietpi-set_cpu

						fi

					fi

				;;

				'CPU Throttle Up')

					MIN_VALUE=30 MAX_VALUE=95
					G_WHIP_DEFAULT_ITEM=$current_cpu_throttle_up
					if G_WHIP_INPUTBOX "When the CPU usage (%) is greater than this value, the CPU frequency will increase from $frequency_min_cpu_governor MHz to $frequency_max_cpu_governor MHz.
 - Valid range: $MIN_VALUE - $MAX_VALUE\n - Recommended settings: Desktop = 50%, Server = 85%" && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE $MAX_VALUE; then

						G_CONFIG_INJECT 'CONFIG_CPU_USAGE_THROTTLE_UP=' "CONFIG_CPU_USAGE_THROTTLE_UP=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
						/boot/dietpi/func/dietpi-set_cpu

					fi

				;;

				'ARM Temp Limit')

					MIN_VALUE=45 MAX_VALUE=85
					G_WHIP_DEFAULT_ITEM=$temp_limit
					if G_WHIP_INPUTBOX "When the ARM temperature ('c) reaches this value, the ARM will underclock to reduce heat.
 - Recommended value: 65\n - Valid range: $MIN_VALUE - $MAX_VALUE" && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE $MAX_VALUE; then

						(( $G_WHIP_RETURNED_VALUE > 65 )) && G_WHIP_MSG "Higher operating temperatures will reduce the life of your ARM SoC. Heat also dissipates through the PCB into other components, decreasing the lifespan of the whole device. Use at your own risk.\n\nDietPi recommends 65'c as a safe value (75'c for RPi 3/4).\n\nMore info: https://github.com/MichaIng/DietPi/issues/356"
						G_CONFIG_INJECT 'temp_limit=' "temp_limit=$G_WHIP_RETURNED_VALUE" /boot/config.txt && REBOOT_REQUIRED=1

					fi

				;;

				'ARM Idle Frequency')

					MIN_VALUE=100
					[[ $G_HW_MODEL == [01] ]] && DEF_VALUE=700 || DEF_VALUE=600
					G_WHIP_DEFAULT_ITEM=$arm_freq_min
					if G_WHIP_INPUTBOX "ARM frequency (MHz) used by CPU governors powersave and schedutil/ondemand/conservative when on idle.
 - Current value: $arm_freq_min\n - Recommended value: 300\n - Minimum value: $MIN_VALUE
 - Default value: $DEF_VALUE\n - Setting a value below the minimum will reset to RPi defaults."; then

						if disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE; then

							G_CONFIG_INJECT 'arm_freq_min=' "arm_freq_min=$G_WHIP_RETURNED_VALUE" /boot/config.txt

						else

							G_EXEC sed -i "/^[[:blank:]]*arm_freq_min=/c\#arm_freq_min=$DEF_VALUE" /boot/config.txt

						fi
						REBOOT_REQUIRED=1

					fi

				;;

				'ARM Initial Turbo')

					MIN_VALUE=1 MAX_VALUE=60
					G_WHIP_DEFAULT_ITEM=$initial_turbo
					if G_WHIP_INPUTBOX "Amount of seconds on boot, where the CPU runs at highest clock, before it starts to respect the CPU governor. This reduces boot time quite much since RPi boots with powersave governor until the chosen one is applied at later boot stage.
 - Recommended value: 20\n - Valid range: $MIN_VALUE - $MAX_VALUE\n - Setting a value outside of range will disable this feature."; then

						if disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $MIN_VALUE $MAX_VALUE; then

							G_CONFIG_INJECT 'initial_turbo=' "initial_turbo=$G_WHIP_RETURNED_VALUE" /boot/config.txt

						else

							sed -i '/^[[:blank:]]*initial_turbo=/c\#initial_turbo=20' /boot/config.txt

						fi
						REBOOT_REQUIRED=1

					fi

				;;

			esac

		fi

	}

	Change_Hostname(){

		local hostname_current=$(</etc/hostname)
		G_WHIP_DEFAULT_ITEM=$hostname_current
		if G_WHIP_INPUTBOX 'Please enter a new hostname:' && [[ $hostname_current != "$G_WHIP_RETURNED_VALUE" ]]; then

			if /boot/dietpi/func/change_hostname "$G_WHIP_RETURNED_VALUE"; then

				REBOOT_REQUIRED=1

			else

				read -rp 'Press any key to return to DietPi-Config...'

			fi

		# Aborted
		else

			G_WHIP_MSG 'Hostname change has been aborted. No changes have been applied.'

		fi

	}

	# TARGETMENUID=5
	Menu_SecurityOptions(){

		TARGETMENUID=0

		G_WHIP_MENU_ARRAY=(

			'1' ': Change Passwords'
			'2' ': Change Hostname'

		)

		if G_WHIP_MENU 'Lock down your DietPi Install'; then

			TARGETMENUID=5 # Return to this menu

			if (( $G_WHIP_RETURNED_VALUE == 1 )); then

				/boot/dietpi/func/dietpi-set_software passwords

			elif (( $G_WHIP_RETURNED_VALUE == 2 )); then

				Change_Hostname

			fi

		fi

	}

	# TARGETMENUID=6
	Menu_GpumemoryOptions(){

		TARGETMENUID=1 # Return to Display Options

		# RPi
		if (( $G_HW_MODEL < 10 )); then

			# Get current memory split
			# - Get override setting: gpu_mem_1024 is effective for all models with >= 1 GiB
			local value=$G_HW_MEMORY_SIZE
			(( $value <= 1024 )) || value=1024
			local gpu_mem_current=$(sed -n "/^[[:blank:]]*gpu_mem_$value=/{s/^[^=]*=//p;q}" /boot/config.txt) # override setting
			[[ $gpu_mem_current ]] || gpu_mem_current=$(sed -n "/^[[:blank:]]*gpu_mem=/{s/^[^=]*=//p;q}" /boot/config.txt) # base setting
			[[ $gpu_mem_current ]] || gpu_mem_current=64 # default value
			local ram_mem_current=$((G_HW_MEMORY_SIZE-gpu_mem_current))

			# Create array for storing menu selectable options.
			G_WHIP_MENU_ARRAY=(

				16 ': Server'
				64 ': Desktop (Low)'
				128 ': Desktop (High)'
				192 ''

			)

			if (( $G_HW_MEMORY_SIZE >= 512 )); then

				G_WHIP_MENU_ARRAY+=(256 ': General Gaming')
				G_WHIP_MENU_ARRAY+=(320 ': Kodi')

				if (( $G_HW_MEMORY_SIZE >= 1024 )); then

					G_WHIP_MENU_ARRAY+=(448 '')
					G_WHIP_MENU_ARRAY+=(512 '')

				fi

			fi

			G_WHIP_DEFAULT_ITEM=$gpu_mem_current
			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $gpu_mem_current MiB GPU | $ram_mem_current MiB RAM"; then

				TARGETMENUID=6 # Return to this menu
				/boot/dietpi/func/dietpi-set_hardware gpumemsplit "$G_WHIP_RETURNED_VALUE" && REBOOT_REQUIRED=1

			fi

		# Odroid C2
		elif (( $G_HW_MODEL == 12 )); then

			# Get current memory split
			local ram_mem_current=$(free -m | mawk '/Mem:/{print $2;exit}')
			local gpu_mem_current=$((2048-ram_mem_current))

			# HDMI/headless extra data
			local display_output_enabled=$(grep -cm1 '^[[:blank:]]*setenv nographics "0"' /boot/boot.ini)
			local display_output_text='On'
			(( $display_output_enabled )) || display_output_text='Off'

			G_WHIP_MENU_ARRAY=(

				'Headless' ': HDMI: Disabled | VPU: Disabled | +300 MiB RAM'
				'Default' ': HDMI: Enabled  | VPU: Enabled | -300 MiB RAM'

			)

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent  : HDMI: [$display_output_text] | VPU: [$display_output_text]\nMemory   : $gpu_mem_current MiB GPU | $ram_mem_current MiB RAM\nNB: GPU/RAM figures require a reboot after a change is made."; then

				TARGETMENUID=6 # Return to this menu
				case "$G_WHIP_RETURNED_VALUE" in

					'Headless') /boot/dietpi/func/dietpi-set_hardware headless 1;;
					'Default') /boot/dietpi/func/dietpi-set_hardware headless 0;;

				esac
				REBOOT_REQUIRED=1

			fi

		else

			Info_HW_OptionNotSupported

		fi

	}

	# TARGETMENUID=7
	Menu_LanguageOptions(){

		local locale_current=$(sed -n '/^[[:blank:]]*AUTO_SETUP_LOCALE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)

		G_WHIP_MENU_ARRAY=(

			'Locale' ": [$locale_current]"
			'Timezone' ": [$(</etc/timezone)]"
			'Keyboard' ": [$(sed -n '/^[[:blank:]]*XKBLAYOUT=/{s/^[^=]*=//;s/"//gp;q}' /etc/default/keyboard)]"

		)

		if G_WHIP_MENU 'Please select an option:'; then

			case "$G_WHIP_RETURNED_VALUE" in

				'Locale')

					until [[ -f '/usr/share/i18n/SUPPORTED' ]]
					do
						G_WHIP_YESNO '[FAILED] No supported locales found
\nShall we try to fix this by (re)installing the locales APT package?' || return 1 && G_AGI --reinstall locales

					done

					G_WHIP_MENU_ARRAY=('C.UTF-8' ': default')
					while read -r line
					do
						G_WHIP_MENU_ARRAY+=("$line" '')

					done <<< "$(mawk '/UTF-8/{print $1}' /usr/share/i18n/SUPPORTED)"

					G_WHIP_DEFAULT_ITEM=$locale_current
					if G_WHIP_MENU 'Please select a system locale. DietPi will automatically apply this as the default locale:'; then

						/boot/dietpi/func/dietpi-set_software locale "$G_WHIP_RETURNED_VALUE" && REBOOT_REQUIRED=1

					fi

				;;

				'Timezone')

					dpkg-reconfigure tzdata

				;;

				'Keyboard')

					G_WHIP_MSG 'NB: A keyboard must be physically plugged into the system, before its configuration can be changed.\n\nIf a keyboard is plugged in, please ignore this message. If not, plug one in ;)'
					dpkg-reconfigure keyboard-configuration
					setupcon --save # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818065

				;;

			esac

		else

			TARGETMENUID=0 # Return to main menu

		fi

	}

	NET_RX_BYTE=0
	NET_TX_BYTE=0
	NET_RX_MB='N/A'
	NET_TX_MB='N/A'

	# $1 = device+index
	Net_Update_UsageStats(){

		local input=$1

		NET_RX_BYTE=0
		NET_TX_BYTE=0
		NET_RX_MB='N/A'
		NET_TX_MB='N/A'

		[[ -f /sys/class/net/$input/statistics/rx_bytes && -f /sys/class/net/$input/statistics/tx_bytes ]] || return

		NET_RX_BYTE=$(<"/sys/class/net/$input/statistics/rx_bytes")
		disable_error=1 G_CHECK_VALIDINT "$NET_RX_BYTE" 1 && NET_RX_MB="$(( $NET_RX_BYTE / 1024 / 1024 )) MiB"
		NET_TX_BYTE=$(<"/sys/class/net/$input/statistics/tx_bytes")
		disable_error=1 G_CHECK_VALIDINT "$NET_TX_BYTE" 1 && NET_TX_MB="$(( $NET_TX_BYTE / 1024 / 1024 )) MiB"

	}

	ETH_IP_STATIC='0.0.0.0'
	ETH_GATEWAY_STATIC='0.0.0.0'
	ETH_MASK_STATIC='0.0.0.0'
	ETH_DNS_STATIC='0.0.0.0'
	ETH_DEV_INDEX=0
	ETH_DISABLED=0
	ETH_HARDWARE=0
	ETH_CONNECTED=0
	ETH_IP='0.0.0.0'
	ETH_GATEWAY='0.0.0.0'
	ETH_MASK='0.0.0.0'
	ETH_MODE=1 # 0=static 1=dhcp
	ETH_MODE_TARGET=0

	WIFI_IP_STATIC='0.0.0.0'
	WIFI_GATEWAY_STATIC='0.0.0.0'
	WIFI_MASK_STATIC='0.0.0.0'
	WIFI_DNS_STATIC='0.0.0.0'
	WIFI_DEV_INDEX=0
	WIFI_DISABLED=0
	WIFI_HARDWARE=0
	WIFI_CONNECTED=0
	WIFI_IP='0.0.0.0'
	WIFI_GATEWAY='0.0.0.0'
	WIFI_MASK='0.0.0.0'
	WIFI_MODE=1 # 0=static 1=dhcp
	WIFI_MODE_TARGET=0
	WIFI_SSID_CURRENT=
	WIFI_BITRATE=0
	WIFI_SIGNALSTRENGTH=0
	WIFI_HOTSPOT=0
	WIFI_COUNTRYCODE='Unknown'
	WIFI_AUTO_RECONNECT_ACTIVE=0

	DNS_CURRENT='0.0.0.0'

	Network_ETH_CopyCurrentToStatic(){

		# Apply if we have a connection
		(( $ETH_CONNECTED )) || return

		ETH_IP_STATIC=$ETH_IP
		ETH_GATEWAY_STATIC=$ETH_GATEWAY
		ETH_MASK_STATIC=$ETH_MASK
		ETH_DNS_STATIC=$DNS_CURRENT

	}

	Network_WIFI_CopyCurrentToStatic(){

		# Apply if we have a connection
		(( $WIFI_CONNECTED )) || return

		WIFI_IP_STATIC=$WIFI_IP
		WIFI_GATEWAY_STATIC=$WIFI_GATEWAY
		WIFI_MASK_STATIC=$WIFI_MASK
		WIFI_DNS_STATIC=$DNS_CURRENT

	}

	Network_Restart(){

		# Stop all services (required for hotspot)
		/boot/dietpi/dietpi-services stop

		# Enable/Disable WiFi modules
		/boot/dietpi/func/dietpi-set_hardware wifimodules $(( ! $WIFI_DISABLED ))

		# Drop Connections
		G_DIETPI-NOTIFY 0 'Dropping connections, please wait...'
		ifdown eth$ETH_DEV_INDEX --force 2> /dev/null
		ifdown wlan$WIFI_DEV_INDEX --force 2> /dev/null

		# Kill dhclient
		killall dhclient 2> /dev/null

		# Flush, not viable to handle this if change of IP, requires a detect of SSH loss/IP change, then exit script.
		#ip a flush dev eth$ETH_DEV_INDEX &> /dev/null
		#ip a flush dev wlan$WIFI_DEV_INDEX &> /dev/null

		# Restart Networking
		G_DIETPI-NOTIFY 2 'Restarting network, please wait...'
		systemctl daemon-reload

		# Manually bring up adapters
		(( $ETH_DISABLED == 0 )) && ifup eth$ETH_DEV_INDEX --force
		(( $WIFI_DISABLED == 0 )) && ifup wlan$WIFI_DEV_INDEX --force

		# Restart all services (required for hotspot)
		/boot/dietpi/dietpi-services start

		# Add a little delay to ensure all network device data are updated (eg: SSID current takes a little longer)
		G_DIETPI-NOTIFY 2 'Reloading networking data, please wait...'
		sleep 2

		# Update network data
		Network_GetData

		G_DIETPI-NOTIFY 0 'Network restarted'

		if [[ $ETH_MODE_TARGET == 0 && $ETH_IP != "$ETH_IP_STATIC" ]] || [[ $WIFI_MODE_TARGET == 0 && $WIFI_IP != "$WIFI_IP_STATIC" ]]; then

			G_WHIP_MSG 'IP STATIC address change detected. A reboot is required to apply the new IP.\n\nPlease reboot the system.'
			REBOOT_REQUIRED=1

		fi

	}

	Network_ApplyChanges(){

		# Check if resolvconf is available, else apply static DNS server via /etc/resolv.conf directly instead of /etc/network/interfaces entry
		local i resolvconf=0
		command -v resolvconf > /dev/null && resolvconf=1
		if (( ! $resolvconf )); then

			if (( ! $ETH_DISABLED && $ETH_MODE_TARGET == 0 )); then

				> /etc/resolv.conf
				for i in $ETH_DNS_STATIC; do echo "nameserver $i" >> /etc/resolv.conf; done

			elif (( ! $WIFI_DISABLED && $WIFI_MODE_TARGET == 0 )); then

				> /etc/resolv.conf
				for i in $WIFI_DNS_STATIC; do echo "nameserver $i" >> /etc/resolv.conf; done

			fi

		fi

		# Eth
		local eth_enabled_text=
		(( $ETH_DISABLED )) && eth_enabled_text='#'
		local eth_dhcp_static_text='dhcp'
		local eth_dns_text='#'
		if (( $ETH_MODE_TARGET == 0 ))
		then
			eth_dhcp_static_text='static'
			(( $resolvconf )) && eth_dns_text=
		fi

		# WiFi
		local wifi_enabled_text=
		(( $WIFI_DISABLED )) && wifi_enabled_text='#'
		local wifi_dhcp_static_text='dhcp'
		local wifi_dns_text='#'
		if (( $WIFI_MODE_TARGET == 0 ))
		then
			wifi_dhcp_static_text='static'
			(( $resolvconf )) && wifi_dns_text=
		fi

		# Create interface config
		local gateway="gateway $ETH_GATEWAY_STATIC"
		[[ $ETH_GATEWAY_STATIC ]] || gateway="#gateway ${ETH_IP_STATIC%.*}.1"
		cat << _EOF_ > /etc/network/interfaces
# Location: /etc/network/interfaces
# Please modify network settings via: dietpi-config
# Or create your own drop-ins in: /etc/network/interfaces.d/

# Drop-in configs
source interfaces.d/*

# Ethernet
${eth_enabled_text}allow-hotplug eth$ETH_DEV_INDEX
iface eth$ETH_DEV_INDEX inet $eth_dhcp_static_text
address $ETH_IP_STATIC
netmask $ETH_MASK_STATIC
$gateway
${eth_dns_text}dns-nameservers $ETH_DNS_STATIC

# WiFi
${wifi_enabled_text}allow-hotplug wlan$WIFI_DEV_INDEX
_EOF_
		# WiFi Hotspot
		if (( $WIFI_HOTSPOT )); then

			cat << _EOF_ >> /etc/network/interfaces
iface wlan$WIFI_DEV_INDEX inet static
address 192.168.42.1
netmask 255.255.255.0
#gateway 192.168.0.1
#dns-nameservers 9.9.9.9 149.112.112.112
wireless-power off

# IP tables
up iptables-restore < /etc/iptables.ipv4.nat
_EOF_
		# WiFi client
		else
			gateway="gateway $WIFI_GATEWAY_STATIC"
			[[ $WIFI_GATEWAY_STATIC ]] || gateway="#gateway ${WIFI_IP_STATIC%.*}.1"
			cat << _EOF_ >> /etc/network/interfaces
iface wlan$WIFI_DEV_INDEX inet $wifi_dhcp_static_text
address $WIFI_IP_STATIC
netmask $WIFI_MASK_STATIC
$gateway
${wifi_dns_text}dns-nameservers $WIFI_DNS_STATIC
wireless-power off
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
_EOF_
		fi

		# Remove wireless-power setting, if not supported by adapter/firmware
		iwconfig wlan$WIFI_DEV_INDEX power off 2> /dev/null || sed -i '/^wireless-power/d' /etc/network/interfaces

		# Update WiFi db/wpa_supplicant
		/boot/dietpi/func/dietpi-wifidb 1

		# Update Current Mode for network restart
		ETH_MODE=$ETH_MODE_TARGET
		WIFI_MODE=$WIFI_MODE_TARGET

		# Restart network
		Network_Restart

	}

	Change_StaticIp(){

		# Ethernet
		if (( $1 == 0 )); then

			G_WHIP_DEFAULT_ITEM=$ETH_IP_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static Ethernet IP address:' && ETH_IP_STATIC=$G_WHIP_RETURNED_VALUE

		# WiFi
		elif (( $1 == 1 )); then

			G_WHIP_DEFAULT_ITEM=$WIFI_IP_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static WiFi IP address:' && WIFI_IP_STATIC=$G_WHIP_RETURNED_VALUE

		fi

	}

	Change_StaticGateway(){

		# Ethernet
		if (( $1 == 0 )); then

			G_WHIP_DEFAULT_ITEM=$ETH_GATEWAY_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static Ethernet gateway address:' && ETH_GATEWAY_STATIC=$G_WHIP_RETURNED_VALUE

		# WiFi
		elif (( $1 == 1 )); then

			G_WHIP_DEFAULT_ITEM=$WIFI_GATEWAY_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static WiFi gateway address:' && WIFI_GATEWAY_STATIC=$G_WHIP_RETURNED_VALUE

		fi

	}

	Change_StaticMask(){

		# Ethernet
		if (( $1 == 0 )); then

			G_WHIP_DEFAULT_ITEM=$ETH_MASK_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static Ethernet network mask:' && ETH_MASK_STATIC=$G_WHIP_RETURNED_VALUE

		# WiFi
		elif (( $1 == 1 )); then

			G_WHIP_DEFAULT_ITEM=$WIFI_MASK_STATIC
			G_WHIP_INPUTBOX 'Please enter a new static WiFi network mask:' && WIFI_MASK_STATIC=$G_WHIP_RETURNED_VALUE

		fi

	}

	Change_StaticDns(){

		# $1 = Adapater type | 0=Eth, 1=WiFi

		# Current value => default choice
		(( $1 )) && G_WHIP_DEFAULT_ITEM=$WIFI_DNS_STATIC || G_WHIP_DEFAULT_ITEM=$ETH_DNS_STATIC

		G_WHIP_MENU_ARRAY=(

			'Custom' ': Manually enter your DNS server'
			'1.1.1.1 1.0.0.1' ': Cloudflare'
			'9.9.9.9 149.112.112.112' ': Quad9'
			'8.8.8.8 8.8.4.4' ': Google'
			'208.67.222.222 208.67.220.220' ': OpenDNS'
			'209.244.0.3 209.244.0.4' ': Level3'
			'216.146.35.35 216.146.36.36' ': Dyn'
			'37.235.1.174 37.235.1.177' ': FreeDNS'
			'64.6.64.6 64.6.65.6' ': Verisign'
			'84.200.69.80 84.200.70.40' ': DNS.WATCH'

		)

		G_WHIP_MENU 'Please select a DNS server, or choose "Custom" for manual entry:' || return
		if [[ $G_WHIP_RETURNED_VALUE == 'Custom' ]]; then

			(( $1 )) && G_WHIP_DEFAULT_ITEM=$WIFI_DNS_STATIC || G_WHIP_DEFAULT_ITEM=$ETH_DNS_STATIC
			G_WHIP_INPUTBOX 'Please enter a new DNS server address\n - 2 maximum, seperated by a space.\n - E.g.: 9.9.9.9 149.112.112.112' || return

		fi

		# Apply new value
		(( $1 )) && WIFI_DNS_STATIC=$G_WHIP_RETURNED_VALUE || ETH_DNS_STATIC=$G_WHIP_RETURNED_VALUE

	}

	Change_WifiCountryCode(){

		local wifi_country_code_target=$WIFI_COUNTRYCODE

		G_WHIP_MENU_ARRAY=(

			'GB' ': Great Britain'
			'DE' ': Germany'
			'US' ': United States'
			'JP' ': Japan'
			'CN' ': China'
			'Manual' ': Enter a custom country code'

		)

		G_WHIP_DEFAULT_ITEM=$WIFI_COUNTRYCODE
		G_WHIP_MENU 'Please select a country, to enable WiFi channels and power ratings allowed in your country.' || return

		if [[ $G_WHIP_RETURNED_VALUE == 'Manual' ]]; then

			G_WHIP_DEFAULT_ITEM=$WIFI_COUNTRYCODE
			G_WHIP_INPUTBOX 'Please enter a 2 character country code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2' || return
			[[ $G_WHIP_RETURNED_VALUE == [[:upper:]][[:upper:]] ]] || { G_WHIP_MSG "[FAILED] Invalid country code ($G_WHIP_RETURNED_VALUE). Aborting..."; return 1; }

		fi
		wifi_country_code_target=$G_WHIP_RETURNED_VALUE

		/boot/dietpi/func/dietpi-set_hardware wificountrycode "$wifi_country_code_target"

		# Restart networking
		Network_Restart

		# Check if country code was successfully applied
		# - Wait a bid until setting got applied
		sleep 0.1
		WIFI_COUNTRYCODE=$(iw reg get | mawk '/country/{print $2;exit}' | tr -d ':')
		if [[ $WIFI_COUNTRYCODE != "$wifi_country_code_target" ]]; then

			G_WHIP_MSG "[FAILED] Country code \"$wifi_country_code_target\" could not been applied.\n\nPlease check the country code and try again.\n\nIf problems persist, this may be a limitation with the driver/chipset."
			return 1

		fi

	}

	Wifi_Reconnect(){

		G_WHIP_YESNO 'WiFi will connect to the strongest configured SSID that is secure, with an open SSID being the last priority.\n
Save all changes and restart networking?\n\nNB: All WiFi connections will be dropped!' && Network_ApplyChanges

	}

	Ethernet_Reconnect(){

		G_WHIP_YESNO 'Do you wish to apply settings and reconnect network now?\n
NB: All Ethernet connections will be dropped!' && Network_ApplyChanges

	}

	INTERNET_TEST_STATE=0 # 0=not tested, 1=failed, 2=online
	INTERNET_TEST_URL='https://dietpi.com'

	Network_GetData(){

		# Update DietPi system network details
		/boot/dietpi/func/obtain_network_details

		# Copy /etc/network/interfaces to /tmp (tmpfs) and pull data from it.
		cp /etc/network/interfaces /tmp/net_interfaces

		# Reset
		ETH_IP_STATIC=$(mawk '$1=="address"{print $2;exit}' /tmp/net_interfaces)
		ETH_GATEWAY_STATIC=$(mawk '$1=="gateway"{print $2;exit}' /tmp/net_interfaces)
		ETH_MASK_STATIC=$(mawk '$1=="netmask"{print $2;exit}' /tmp/net_interfaces)
		ETH_DNS_STATIC=$(mawk '$1~/#?dns-nameservers/{print $2,$3;exit}' /tmp/net_interfaces)
		# Remove trailing space in case of single nameserver, due to mawk '{print $2,$3}'
		ETH_DNS_STATIC=${ETH_DNS_STATIC%[[:blank:]]}
		ETH_DEV_INDEX=$(mawk 'NR==1' /run/dietpi/.network)
		ETH_DISABLED=$(( ! $(grep -Ecm1 "^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+eth$ETH_DEV_INDEX" /tmp/net_interfaces) ))
		ETH_HARDWARE=0
		ETH_CONNECTED=0
		ETH_IP='0.0.0.0'
		ETH_GATEWAY='0.0.0.0'
		ETH_MASK='0.0.0.0'
		ETH_MODE=1
		ETH_MODE_TARGET=$ETH_MODE

		WIFI_IP_STATIC=$(mawk '$1=="address"{print $2}' /tmp/net_interfaces | mawk 'NR==2')
		WIFI_GATEWAY_STATIC=$(mawk '$1=="gateway"{print $2}' /tmp/net_interfaces | mawk 'NR==2')
		WIFI_MASK_STATIC=$(mawk '$1=="netmask"{print $2}' /tmp/net_interfaces | mawk 'NR==2')
		WIFI_DNS_STATIC=$(mawk '$1~/#?dns-nameservers/{print $2,$3}' /tmp/net_interfaces | mawk 'NR==2')
		# Remove trailing space in case of single nameserver, due to mawk '{print $2,$3}'
		WIFI_DNS_STATIC=${WIFI_DNS_STATIC%[[:blank:]]}
		WIFI_DEV_INDEX=$(mawk 'NR==2' /run/dietpi/.network)
		WIFI_DISABLED=$(( ! $(grep -Ecm1 "^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+wlan$WIFI_DEV_INDEX" /tmp/net_interfaces) ))
		WIFI_HARDWARE=0
		WIFI_CONNECTED=0
		WIFI_IP='0.0.0.0'
		WIFI_GATEWAY='0.0.0.0'
		WIFI_MASK='0.0.0.0'
		WIFI_MODE=1
		WIFI_MODE_TARGET=$WIFI_MODE

		DNS_CURRENT=$(mawk '$1=="nameserver"{print $2}' ORS=' ' /etc/resolv.conf)
		DNS_CURRENT=${DNS_CURRENT% }

		# Get extra WiFi stats
		command -v iwgetid &> /dev/null && WIFI_SSID_CURRENT=$(iwgetid -r)
		[[ $WIFI_SSID_CURRENT ]] || WIFI_SSID_CURRENT='Disconnected / No SSID'
		WIFI_BITRATE=0
		WIFI_SIGNALSTRENGTH=0
		command -v hostapd &> /dev/null && WIFI_HOTSPOT=1 || WIFI_HOTSPOT=0
		WIFI_COUNTRYCODE='GB'
		# Prevent "nl80211 not found" message, when running this command with cfg80211 module disabled.
		command -v iw &> /dev/null && WIFI_COUNTRYCODE=$(iw reg get | mawk '/country/{print $2;exit}' | tr -d ':')

		# Convert CIDR integer to net mask, e.g. "192.168.0.100/24" (take "24") to "255.255.255.0"
		cidr2mask()
		{
			local i mask full_octets=$(( $1 / 8 )) partial_octet=$(( $1%8 ))
			for i in {0..3}
			do
				if (( $i < $full_octets ))
				then
					mask+=255

				elif (( $i == $full_octets ))
				then
					mask+=$(( 256 - 2 ** ( 8 - $partial_octet ) ))

				else
					mask+=0
				fi
				(( $i < 3 )) && mask+=.
			done
			echo $mask
		}

		# Eth
		if [[ -d /sys/class/net/eth$ETH_DEV_INDEX ]]; then

			# Hardware
			ETH_HARDWARE=1

			# Static or DHCP?
			ETH_MODE=$(grep -cm1 "iface eth$ETH_DEV_INDEX inet dhcp" /tmp/net_interfaces)
			ETH_MODE_TARGET=$ETH_MODE

			# Connected and valid IP?
			ETH_CONNECTED=$(ip -o r l dev "eth$ETH_DEV_INDEX" | grep -vcm1 '[[:blank:]]linkdown')

			# Enabled and connected
			if (( ! $ETH_DISABLED && $ETH_CONNECTED )); then

				ETH_IP=$(ip -br -f inet a s "eth$ETH_DEV_INDEX" | mawk '{print $3}' | sed 's|/.*$||')
				ETH_GATEWAY=$(ip r l dev "eth$ETH_DEV_INDEX" 0/0 | mawk '{print $3;exit}')
				ETH_MASK=$(cidr2mask "$(ip -br -f inet a s "eth$ETH_DEV_INDEX" | mawk '{print $3}' | sed 's|^.*/||')")

			fi

		fi

		# WiFi
		if [[ -d /sys/class/net/wlan$WIFI_DEV_INDEX ]]; then

			# Hardware
			WIFI_HARDWARE=1

			# Static or DHCP?
			WIFI_MODE=$(grep -cm1 "iface wlan$WIFI_DEV_INDEX inet dhcp" /tmp/net_interfaces)
			WIFI_MODE_TARGET=$WIFI_MODE

			# Connected and valid IP?
			WIFI_CONNECTED=$(ip -o r l dev "wlan$ETH_DEV_INDEX" | grep -vcm1 '[[:blank:]]linkdown')

			# Enabled and connected
			if (( ! $WIFI_DISABLED && $WIFI_CONNECTED )); then

				WIFI_IP=$(ip -br -f inet a s "wlan$WIFI_DEV_INDEX" | mawk '{print $3}' | sed 's|/.*$||')
				WIFI_GATEWAY=$(ip r l dev "wlan$WIFI_DEV_INDEX" 0/0 | mawk '{print $3;exit}')
				WIFI_MASK=$(cidr2mask "$(ip -br -f inet a s "wlan$WIFI_DEV_INDEX" | mawk '{print $3}' | sed 's|^.*/||')")

				# Get extra WiFi stats
				WIFI_BITRATE=$(iwconfig "wlan$WIFI_DEV_INDEX" | mawk '/Bit Rate/{print $2;exit}' | sed 's/Rate[:=]//g')
				WIFI_SIGNALSTRENGTH=$(iwconfig "wlan$WIFI_DEV_INDEX" | mawk '/Signal level=/{print $4;exit}' | sed 's/level=//g' | cut -f1 -d "/")

				# Try and detect if this is dBm (contains -) or %
				if disable_error=1 G_CHECK_VALIDINT "$WIFI_SIGNALSTRENGTH" -500 -1; then

					WIFI_SIGNALSTRENGTH="$WIFI_SIGNALSTRENGTH dBm"

				else

					WIFI_SIGNALSTRENGTH="$WIFI_SIGNALSTRENGTH %"

				fi

			fi

		fi

		# Cleanup tmp
		[[ -f '/tmp/net_interfaces' ]] && rm /tmp/net_interfaces

	}

	# TARGETMENUID=8
	Menu_NetworkAdapters(){

		# Check Network
		Network_GetData

		# Obtain enabled/disabled status
		local eth_disabled_text='On'
		(( $ETH_DISABLED )) && eth_disabled_text='Off'

		local wlan_disabled_text='On'
		(( $WIFI_DISABLED )) && wlan_disabled_text='Off'

		# Obtain Hardware Status
		local eth_hardware_text='Available'
		(( $ETH_HARDWARE )) || eth_hardware_text='Not Found'

		local wlan_hardware_text='Available'
		(( $WIFI_HARDWARE )) || wlan_hardware_text='Not Found'

		# Obtain Connected/Carrier Status
		local eth_connected_text='Disconnected'
		(( $ETH_CONNECTED )) && eth_connected_text='Connected'

		local wlan_connected_text='Disconnected'
		if (( $WIFI_CONNECTED )); then

			(( $WIFI_HOTSPOT )) && wlan_connected_text='WiFi Hotspot Mode' || wlan_connected_text='Connected'

		fi

		# Internet Connection Status
		local Internet_connected_text='Run internet connection test'
		if (( $INTERNET_TEST_STATE == 2 )); then

			Internet_connected_text='[Success] | Online'

		elif (( $INTERNET_TEST_STATE == 1 )); then

			Internet_connected_text='[Failure] | Offline'

		fi

		# Proxy settings: Scrapes $http_proxy, otherwise obtains current values stored in dietpi.txt
		Load_Proxy_Vars

		local proxy_state_text='[Off]'
		(( $PROXY_ENABLED )) && proxy_state_text="[On] | $PROXY_ADDRESS:$PROXY_PORT"

		G_WHIP_MENU_ARRAY=('' '●─ Adapter Options ')
		G_WHIP_MENU_ARRAY+=('Ethernet' ": $eth_hardware_text | [$eth_disabled_text] | $eth_connected_text")
		G_WHIP_MENU_ARRAY+=('WiFi' ": $wlan_hardware_text | [$wlan_disabled_text] | $wlan_connected_text")

		# Onboard WiFi
		# - RPi 3/4/Zero W
		if (( $G_HW_ONBOARD_WIFI )); then

			local onboard_wifi_enabled=1
			if grep -q '^[[:blank:]]*dtoverlay=disable-wifi' /boot/config.txt; then

				onboard_wifi_enabled=0
				G_WHIP_MENU_ARRAY+=('Onboard WiFi' ': [Off]')

			else

				G_WHIP_MENU_ARRAY+=('Onboard WiFi' ': [On]')

			fi

		fi

		G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')

		# IPv6
		if [[ -d '/proc/sys/net/ipv6' ]]; then

			local ipv6_enabled=0
			local ipv6_status_text='Off'
			if [[ $(ip -6 a) ]]; then

				ipv6_enabled=1
				ipv6_status_text='On'

			fi
			G_WHIP_MENU_ARRAY+=('IPv6' ": [$ipv6_status_text]")
			# Only offer to prefer IPv4, if IPv6 is enabled
			if (( $ipv6_enabled )); then

				local ipv4_preferred=0
				local ipv4_status_text='Off'
				if [[ -f '/etc/apt/apt.conf.d/99-dietpi-force-ipv4' ]]; then

					ipv4_preferred=1
					ipv4_status_text='On'

				fi
				G_WHIP_MENU_ARRAY+=('Prefer IPv4' ": [$ipv4_status_text]")

			fi

		fi

		G_WHIP_MENU_ARRAY+=('Proxy' ": $proxy_state_text")
		G_WHIP_MENU_ARRAY+=('Test' ": $Internet_connected_text")

		if G_WHIP_MENU 'Please select an option to change:'; then

			case "$G_WHIP_RETURNED_VALUE" in

				'Onboard WiFi')

					if (( $onboard_wifi_enabled )); then

						/boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable

					else

						/boot/dietpi/func/dietpi-set_hardware wifimodules onboard_enable

					fi
					REBOOT_REQUIRED=1

				;;

				'IPv6')

					/boot/dietpi/func/dietpi-set_hardware enableipv6 $(( ! $ipv6_enabled ))

				;;

				'Prefer IPv4')

					/boot/dietpi/func/dietpi-set_hardware preferipv4 $(( ! $ipv4_preferred ))

				;;

				'Ethernet')

					# No hardware found
					if (( ! $ETH_HARDWARE )); then

						G_WHIP_MSG 'No Ethernet hardware was detected on your device.'

					# Disabled
					elif (( $ETH_DISABLED )); then

						if G_WHIP_YESNO 'Ethernet must be enabled before settings can be changed.
\nWould you like to enable Ethernet now?\n - (NOTICE) Connections may drop!'; then

							ETH_DISABLED=0
							Network_ApplyChanges
							TARGETMENUID=9

						fi

					else

						TARGETMENUID=9

					fi

				;;

				'WiFi')

					# Disabled | Offer chance to enable (also enables WiFi modules)
					if (( $WIFI_DISABLED )); then

						if G_WHIP_YESNO 'WiFi must be enabled before settings can be changed.
\nWould you like to enable WiFi now?\n - NB: Connections may drop!'; then

							WIFI_DISABLED=0
							Network_ApplyChanges

						fi

					# No hardware found
					elif (( ! $WIFI_HARDWARE )); then

						if G_WHIP_YESNO 'No supported WiFi hardware was found.
\nWould you like to disable WiFi?\n - NB: Connections may drop!'; then

							WIFI_DISABLED=1
							Network_ApplyChanges

						fi

					else

						TARGETMENUID=10

					fi

				;;

				'Test')

					G_WHIP_DEFAULT_ITEM=$INTERNET_TEST_URL
					if G_WHIP_INPUTBOX 'Please enter a URL address to test, e.g.: https://dietpi.com'; then

						INTERNET_TEST_URL=$G_WHIP_RETURNED_VALUE

						INTERNET_TEST_STATE=0 # Not tested
						if G_EXEC_NOHALT=1 G_CHECK_URL "$INTERNET_TEST_URL"; then

							INTERNET_TEST_STATE=2 # Online

						else

							INTERNET_TEST_STATE=1 # Failed

						fi

					fi

				;;

				'Proxy')

					TARGETMENUID=17

				;;

			esac

		# Cancel
		else

			TARGETMENUID=0 # Return to main menu

			# Exit DietPi-Config on back to previous menu?
			if (( $EXITONBACK == 1 )); then

				TARGETMENUID=8 # Return to this menu
				Menu_Exit

			fi

		fi

	}

	# TARGETMENUID=9
	Menu_NetworkAdapters_Ethernet(){

		TARGETMENUID=8

		# Mode
		local mode_text='DHCP'
		(( $ETH_MODE_TARGET == 0 )) && mode_text='STATIC'
		G_WHIP_MENU_ARRAY=('' '●─ DHCP/STATIC IP ')
		G_WHIP_MENU_ARRAY+=('Change Mode' ": [$mode_text]")

		# Show static options
		if (( $ETH_MODE_TARGET == 0 )); then

			G_WHIP_MENU_ARRAY+=('Copy' ': Copy current address to "Static"')
			G_WHIP_MENU_ARRAY+=('Static IP' ": [$ETH_IP_STATIC]")
			G_WHIP_MENU_ARRAY+=('Static Mask' ": [$ETH_MASK_STATIC]")
			G_WHIP_MENU_ARRAY+=('Static Gateway' ": [$ETH_GATEWAY_STATIC]")
			G_WHIP_MENU_ARRAY+=('Static DNS' ": [$ETH_DNS_STATIC]")

		fi

		G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')
		local eth_speed='auto (default)'
		[[ -f '/etc/systemd/system/ethtool_force_speed.service' ]] && eth_speed=$(mawk '/^ExecStart=/{print $5;exit}' /etc/systemd/system/ethtool_force_speed.service)
		G_WHIP_MENU_ARRAY+=('Link Speed' ": [$eth_speed]")
		G_WHIP_MENU_ARRAY+=('Disable' ': Disable Ethernet adapter')

		G_WHIP_MENU_ARRAY+=('' '●─ Apply ')
		G_WHIP_MENU_ARRAY+=('Apply' ': Save all changes and restart networking')

		Net_Update_UsageStats "eth$ETH_DEV_INDEX"

		G_WHIP_DEFAULT_ITEM=$WHIP_SELECTION_PREVIOUS
		if G_WHIP_MENU "Ethernet Details:\nUsage   : Sent = $NET_TX_MB | Recieved = $NET_RX_MB\nAddress : IP = $ETH_IP | Mask = $ETH_MASK | Gateway = $ETH_GATEWAY | DNS = $DNS_CURRENT"; then

			TARGETMENUID=9 # Return to this menu

			WHIP_SELECTION_PREVIOUS=$G_WHIP_RETURNED_VALUE

			case "$G_WHIP_RETURNED_VALUE" in

				'Change Mode')

					((ETH_MODE_TARGET++))
					(( $ETH_MODE_TARGET >= 2 )) && ETH_MODE_TARGET=0

				;;

				'Link Speed')

					G_AG_CHECK_INSTALL_PREREQ ethtool
					G_WHIP_MENU_ARRAY=('0' ': Auto-negotiation (default, recommended)')
					while read -r speed
					do
						speed=${speed//[^0-9]}
						[[ $speed ]] && G_WHIP_MENU_ARRAY+=("$speed" ": Force $speed Mbit link speed")

					done < <(ethtool "eth$ETH_DEV_INDEX" | sed -n '/Supported link modes:/,/^[[:blank:]]*[[:alpha:]]/p' | head -n -1 | mawk '{print $NF}')
					G_WHIP_MENU 'Please select a supported Ethernet link speed to force or auto-negotiation.
NB: Auto-negotiation is highly recommended as long as you do not have issues with the auto estimated link speed.
    This is mainly aimed at PINE A64 which may have a hardware issue that causes unstable 1000 Mbit link.' && /boot/dietpi/func/dietpi-set_hardware eth-forcespeed "$G_WHIP_RETURNED_VALUE"

				;;

				'Disable')

					if G_WHIP_YESNO 'Would you like to disable the Ethernet adapter?\n - (NOTICE) All Ethernet connections will be dropped.'; then

						ETH_DISABLED=1
						Network_ApplyChanges
						TARGETMENUID=8

					fi

				;;

				'Apply')

					Ethernet_Reconnect

				;;

				'Copy')

					Network_ETH_CopyCurrentToStatic

				;;

				'Static IP')

					Change_StaticIp 0

				;;

				'Static Gateway')

					Change_StaticGateway 0

				;;

				'Static Mask')

					Change_StaticMask 0

				;;

				'Static DNS')

					Change_StaticDns 0

				;;

			esac

		fi

	}

	HOTSPOT_SSID=
	HOTSPOT_CHANNEL=
	HOTSPOT_KEY=

	WiFi_Monitor_Disable(){ systemctl disable --now dietpi-wifi-monitor; }

	WiFi_Monitor_Enable(){ G_EXEC systemctl enable --now dietpi-wifi-monitor; }

	# TARGETMENUID=10
	Menu_NetworkAdapters_Wifi(){

		TARGETMENUID=8

		Net_Update_UsageStats "wlan$WIFI_DEV_INDEX"

		local description_text="WiFi Details:\nUsage   : Sent = $NET_TX_MB | Recieved = $NET_RX_MB\n"

		G_WHIP_MENU_ARRAY=('' '●─ Basic Options ')

		# WiFi Hotspot Menu
		if (( $WIFI_HOTSPOT )); then

			# Load current details into global vars, once.
			if [[ ! $HOTSPOT_SSID ]]; then

				HOTSPOT_SSID=$(sed -n '/^[[:blank:]]*ssid=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
				HOTSPOT_CHANNEL=$(sed -n '/^[[:blank:]]*channel=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)
				HOTSPOT_KEY=$(sed -n '/^[[:blank:]]*wpa_passphrase=/{s/^[^=]*=//p;q}' /etc/hostapd/hostapd.conf)

			fi

			# N enabled?
			local hotspot_n_enabled=0
			local hotspot_n_text='Disabled'
			if grep -q '^ieee80211n=1' /etc/hostapd/hostapd.conf; then

				hotspot_n_enabled=1
				hotspot_n_text='Enabled'

			fi

			# Toggle
			local hotspot_active_state=$(systemctl is-active hostapd | grep -cim1 '^active' )
			local hotspot_status_text='Status  : Offline'
			local hotspot_active_state_text='[Disabled] | Select to turn on hotspot'
			if (( $hotspot_active_state )); then

				hotspot_status_text+='Status  : Online'
				hotspot_active_state_text='[Enabled] | Select to turn off hotspot'

			fi

			G_WHIP_MENU_ARRAY+=('SSID' ": [$HOTSPOT_SSID]")
			G_WHIP_MENU_ARRAY+=('Channel' ": [$HOTSPOT_CHANNEL]")
			G_WHIP_MENU_ARRAY+=('Key' ": [$HOTSPOT_KEY]")
			G_WHIP_MENU_ARRAY+=('802.11 N' ": [$hotspot_n_text]")

			description_text+=$hotspot_status_text

		# WiFi Menu
		else

			# Mode
			local mode_text='DHCP'
			(( $WIFI_MODE_TARGET )) || mode_text='STATIC'

			G_WHIP_MENU_ARRAY+=('Scan' ': Scan and configure SSID')

			if (( $WIFI_CONNECTED )) || systemctl is-active dietpi-wifi-monitor | grep -qi '^active'; then

				local wifi_auto_reconnect_text='Off'
				WIFI_AUTO_RECONNECT_ACTIVE=0
				if systemctl is-active dietpi-wifi-monitor | grep -qi '^active'; then

					WIFI_AUTO_RECONNECT_ACTIVE=1
					wifi_auto_reconnect_text='On'

				fi

				G_WHIP_MENU_ARRAY+=('Auto Reconnect' ": [$wifi_auto_reconnect_text]")

			fi

			G_WHIP_MENU_ARRAY+=('' '●─ DHCP/STATIC IP ')
			G_WHIP_MENU_ARRAY+=('Change Mode' ": [$mode_text]")

			# Show static options
			if (( $WIFI_MODE_TARGET == 0 )); then

				G_WHIP_MENU_ARRAY+=('Copy' ': Copy current address to "Static"')
				G_WHIP_MENU_ARRAY+=('Static IP' ": [$WIFI_IP_STATIC]")
				G_WHIP_MENU_ARRAY+=('Static Mask' ": [$WIFI_MASK_STATIC]")
				G_WHIP_MENU_ARRAY+=('Static Gateway' ": [$WIFI_GATEWAY_STATIC]")
				G_WHIP_MENU_ARRAY+=('Static DNS' ": [$WIFI_DNS_STATIC]")

			fi

			description_text+="SSID    : $WIFI_SSID_CURRENT | $WIFI_BITRATE Mbit | Strength: $WIFI_SIGNALSTRENGTH\nAddress : IP = $WIFI_IP | Mask = $WIFI_MASK | Gateway = $WIFI_GATEWAY | DNS = $DNS_CURRENT"

		fi

		G_WHIP_MENU_ARRAY+=('' '●─ Additional Options ')
		# - Unset country code?
		if [[ $WIFI_COUNTRYCODE == '00' ]]; then

			G_WHIP_MENU_ARRAY+=('Country' ": [$WIFI_COUNTRYCODE] (Not set, please configure)")
		else

			G_WHIP_MENU_ARRAY+=('Country' ": [$WIFI_COUNTRYCODE]")

		fi

		G_WHIP_MENU_ARRAY+=('' '●─ Toggle State ')
		if (( $WIFI_HOTSPOT )); then

			G_WHIP_MENU_ARRAY+=('State' ": $hotspot_active_state_text")

		else

			G_WHIP_MENU_ARRAY+=('Disable' ': Disable WiFi adapter')

		fi

		G_WHIP_MENU_ARRAY+=('' '●─ Apply ')
		G_WHIP_MENU_ARRAY+=('Apply' ': Save all changes and restart networking')

		G_WHIP_DEFAULT_ITEM=$WHIP_SELECTION_PREVIOUS
		if G_WHIP_MENU "$description_text"; then

			TARGETMENUID=10 # Return to this menu

			WHIP_SELECTION_PREVIOUS=$G_WHIP_RETURNED_VALUE

			case "$G_WHIP_RETURNED_VALUE" in

				'Auto Reconnect')

					if (( $WIFI_AUTO_RECONNECT_ACTIVE )); then

						WiFi_Monitor_Disable

					else

						WiFi_Monitor_Enable

					fi

				;;

				'Key')

					G_WHIP_DEFAULT_ITEM=$HOTSPOT_KEY
					G_WHIP_INPUTBOX 'Please enter a key/password for the WiFi hotspot\n - NB: Minimum of 8 characters' && HOTSPOT_KEY=$G_WHIP_RETURNED_VALUE

				;;

				'SSID')

					G_WHIP_DEFAULT_ITEM=$HOTSPOT_SSID
					G_WHIP_INPUTBOX 'Please enter a SSID for the WiFi hotspot' && HOTSPOT_SSID=$G_WHIP_RETURNED_VALUE

				;;

				'Channel')

					# 2.4ghz only atm
					local channel_mhz=2412
					local channel_min=1
					local channel_max=13
					G_WHIP_MENU_ARRAY=()
					for ((i=$channel_min; i<=$channel_max; i++))
					do
						G_WHIP_MENU_ARRAY+=("$i" ": $channel_mhz MHz")
						((channel_mhz+=5))
					done

					G_WHIP_DEFAULT_ITEM=$HOTSPOT_CHANNEL
					G_WHIP_MENU 'Please select a WiFi channel for the hotspot.' && HOTSPOT_CHANNEL=$G_WHIP_RETURNED_VALUE

				;;

				'802.11 N')

					(( $hotspot_n_enabled )) && hotspot_n_enabled=0 || hotspot_n_enabled=1
					G_CONFIG_INJECT 'ieee80211n=' "ieee80211n=$hotspot_n_enabled" /etc/hostapd/hostapd.conf

				;;

				'Country')

					Change_WifiCountryCode

				;;

				'Disable')

					G_WHIP_YESNO 'Would you like to disable the WiFi adapter?\n - (NOTICE) All WiFi connections will be dropped.' || return
					WIFI_DISABLED=1
					WiFi_Monitor_Disable
					Network_ApplyChanges
					TARGETMENUID=8

				;;

				'Scan')

					/boot/dietpi/func/dietpi-wifidb

				;;

				'Change Mode')

					((WIFI_MODE_TARGET++))
					if (( $WIFI_MODE_TARGET >= 2 )); then

						WIFI_MODE_TARGET=0
						G_WHIP_MSG 'Information for STATIC IP:\n\nWhen using STATIC IP, please ensure only 1 SSID entry exists in the "Scan" menu. Else, WiFi will most likely fail, and, the IP conflict committee will be displeased ;)'

					fi

				;;

				'Apply')

					if (( $WIFI_HOTSPOT == 1 )); then

						# - update dietpi.txt
						sed -i "/SOFTWARE_WIFI_HOTSPOT_SSID=/c\SOFTWARE_WIFI_HOTSPOT_SSID=$HOTSPOT_SSID" /boot/dietpi.txt
						sed -i "/SOFTWARE_WIFI_HOTSPOT_CHANNEL=/c\SOFTWARE_WIFI_HOTSPOT_CHANNEL=$HOTSPOT_CHANNEL" /boot/dietpi.txt
						sed -i "/SOFTWARE_WIFI_HOTSPOT_KEY=/c\SOFTWARE_WIFI_HOTSPOT_KEY=$HOTSPOT_KEY" /boot/dietpi.txt

						# - update hostapd conf
						sed -i "/ssid=/c\ssid=$HOTSPOT_SSID" /etc/hostapd/hostapd.conf
						sed -i "/channel=/c\channel=$HOTSPOT_CHANNEL" /etc/hostapd/hostapd.conf
						sed -i "/wpa_passphrase=/c\wpa_passphrase=$HOTSPOT_KEY" /etc/hostapd/hostapd.conf

						# - Apply/Restart network
						Network_ApplyChanges

					else

						Wifi_Reconnect

					fi

				;;

				'Copy')

					Network_WIFI_CopyCurrentToStatic

				;;

				'Static IP')

					Change_StaticIp 1

				;;

				'Static Gateway')

					Change_StaticGateway 1

				;;

				'Static Mask')

					Change_StaticMask 1

				;;

				'Static DNS')

					Change_StaticDns 1

				;;

				'State')

					if (( $hotspot_active_state )); then

						G_EXEC systemctl stop hostapd

					else

						G_EXEC systemctl start hostapd

					fi

				;;

			esac

		fi

	}

	# TARGETMENUID=11
	Menu_Tools(){

		TARGETMENUID=0

		G_WHIP_MENU_ARRAY=(

			'Benchmarks' ': CPU, RAM, LAN and filesystem benchmarks'
			'Stress Test' ': CPU Burn and system stability tests (CPU/IO/RAM)'

		)

		if G_WHIP_MENU 'Please select an option:'; then

			case "$G_WHIP_RETURNED_VALUE" in

				'Benchmarks')

					TARGETMENUID=12

				;;

				'Stress Test')

					TARGETMENUID=15

				;;

			esac

		fi

	}

	# TARGETMENUID=12
	Menu_FilesystemBenchmark(){

		TARGETMENUID=11

		# Init/load previous bench results
		[[ -f '/var/lib/dietpi/dietpi-benchmark/results' ]] || /boot/dietpi/func/dietpi-benchmark 0
		. /var/lib/dietpi/dietpi-benchmark/results

		# Sanity for beta testing. As this value won't exist until re-save of /var/lib/dietpi/dietpi-benchmark/results
		[[ $BENCH_NET_LAN_SPEED ]] || BENCH_NET_LAN_SPEED='Not Tested'

		G_WHIP_MENU_ARRAY=(

			'' '●─ DietPi-Benchmark '
			'DietPi-Benchmark' ': Starts CPU, RAM and IO benchmark suite. Scores can be viewed online.'
			'' '●─ Additional benchmarks '
			'Custom Filesystem' ': Benchmark IO performance from a selection of mounted devices.'
			'Network LAN' ': Benchmark LAN performance using 2 DietPi systems.'

		)

		G_WHIP_DEFAULT_ITEM='DietPi-Benchmark'
		if G_WHIP_MENU "\
DietPi-Benchmark | https://dietpi.com/survey#benchmark :
 - CPU Performance   : Duration = $BENCH_CPU seconds (lower is faster)
 - CPU Temp          : Idle = ${BENCH_CPU_TEMP_START}'c | Full load = ${BENCH_CPU_TEMP_END}'c
 - RootFS            : Write = $BENCH_ROOTFS_WRITE MB/s | Read = $BENCH_ROOTFS_READ MB/s
 - RAM               : Write = $BENCH_RAM_WRITE MB/s | Read = $BENCH_RAM_READ MB/s

Additional benchmarks:
 - Custom Filesystem : Write = $BENCH_CUSTOMFS_WRITE MB/s | Read = $BENCH_CUSTOMFS_READ MB/s
 - Network LAN       : Transfer rate = $BENCH_NET_LAN_SPEED MB/s"; then

			TARGETMENUID=12 # Return to this menu

			case "$G_WHIP_RETURNED_VALUE" in

				'DietPi-Benchmark')

					/boot/dietpi/func/dietpi-benchmark 2

				;;

				'Network LAN')

					G_WHIP_MENU_ARRAY=(

						'Server' ': Run this device as the server'
						'Client' ': Connect to an existing server, to begin the test'

					)

					if G_WHIP_MENU 'Please select an option:\n\n - Server: Run a server on the current device. Another system can then use the "Client" option to connect and begin the test.\n\n - Client: Connect to an existing server and begin the test.'; then

						if [[ $G_WHIP_RETURNED_VALUE == 'Server' ]]; then

							/boot/dietpi/func/dietpi-benchmark 3

						elif [[ $G_WHIP_RETURNED_VALUE == 'Client' ]]; then

							/boot/dietpi/func/dietpi-benchmark 4

						fi

					fi

				;;

				'Custom Filesystem')

					/boot/dietpi/dietpi-drive_manager 1
					local fp_fsbench_custom_mount=$(</tmp/dietpi-drive_manager_selmnt)

					if [[ $fp_fsbench_custom_mount ]]; then

						FP_BENCHFILE=$fp_fsbench_custom_mount /boot/dietpi/func/dietpi-benchmark 1

					fi

				;;

			esac

		fi

	}

	Reset_Overclocking(){

		# Defaults: https://github.com/raspberrypi/documentation/blob/master/configuration/config-txt/overclocking.md

		sed -i '/over_voltage=/c\#over_voltage=0' /boot/config.txt

		if (( $G_HW_MODEL == 4 )); then

			sed -i '/arm_freq=/c\#arm_freq=1500' /boot/config.txt
			sed -i '/core_freq=/c\#core_freq=500' /boot/config.txt
			sed -i '/sdram_freq=/d' /boot/config.txt

		elif (( $G_HW_MODEL == 3 )); then

			sed -i '/core_freq=/c\#core_freq=400' /boot/config.txt

			if [[ $G_HW_MODEL_NAME == *'+'* ]]; then

				sed -i '/arm_freq=/c\#arm_freq=1400' /boot/config.txt
				sed -i '/sdram_freq=/c\#sdram_freq=500' /boot/config.txt

			else

				sed -i '/arm_freq=/c\#arm_freq=1200' /boot/config.txt
				sed -i '/sdram_freq=/c\#sdram_freq=450' /boot/config.txt

			fi

		elif (( $G_HW_MODEL == 2 )); then

			sed -i '/arm_freq=/c\#arm_freq=900' /boot/config.txt
			sed -i '/core_freq=/c\#core_freq=250' /boot/config.txt
			sed -i '/sdram_freq=/c\#sdram_freq=450' /boot/config.txt

		elif (( $G_HW_MODEL < 2 )); then

			if [[ $G_HW_MODEL_NAME == *'Zero'* ]]; then

				sed -i '/arm_freq=/c\#arm_freq=1000' /boot/config.txt
				sed -i '/core_freq=/c\#core_freq=400' /boot/config.txt
				sed -i '/sdram_freq=/c\#sdram_freq=450' /boot/config.txt

			else

				sed -i '/arm_freq=/c\#arm_freq=700' /boot/config.txt
				sed -i '/core_freq=/c\#core_freq=250' /boot/config.txt
				sed -i '/sdram_freq=/c\#sdram_freq=400' /boot/config.txt

			fi

		fi

		REBOOT_REQUIRED=1

	}

	Warning_Overclocking(){

		G_WHIP_YESNO 'The selected overclocking choice may void the warranty on this device. Do you wish to continue?\n\nUse of this tool is at your own risk. DietPi will not be held responsable for any damages due to overclocking.\n\nAlthough DietPi overclocks are tested for stability, results are not guaranteed and may differ from device.'

	}

	# TARGETMENUID=13
	Menu_Overclock(){

		TARGETMENUID=4

		# Get Current Overclocking Settings
		local over_voltage_value=$(sed -n '/over_voltage=/{s/^[^=]*=//p;q}' /boot/config.txt)
		local arm_freq_value=$(sed -n '/arm_freq=/{s/^[^=]*=//p;q}' /boot/config.txt)
		local core_freq_value=$(sed -n '/core_freq=/{s/^[^=]*=//p;q}' /boot/config.txt)
		(( $G_HW_MODEL == 4 )) || local sdram_freq_value=$(sed -n '/sdram_freq=/{s/^[^=]*=//p;q}' /boot/config.txt)

		# RPi Zero
		if [[ $G_HW_MODEL_NAME == 'RPi Zero'* ]]; then

			G_WHIP_MENU_ARRAY=('none' ': 1000 MHz ARM | 400 MHz core | 450 MHz SDRAM | 0 overvolt')

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $arm_freq_value MHz ARM | $core_freq_value MHz core | $sdram_freq_value MHz SDRAM | $over_voltage_value overvolt"; then

				TARGETMENUID=13 # Return to this menu

				case "$G_WHIP_RETURNED_VALUE" in

					'none') Reset_Overclocking;;

				esac

			fi

		# RPi 1
		elif (( $G_HW_MODEL < 2 )); then

			G_WHIP_MENU_ARRAY=(

				'none' ':  700 MHz ARM | 250 MHz core | 400 MHz SDRAM | 0 overvolt'
				'safe' ':  900 MHz ARM | 250 MHz core | 400 MHz SDRAM | 2 overvolt'
				'high' ':  900 MHz ARM | 500 MHz core | 400 MHz SDRAM | 4 overvolt'
				'extreme' ': 1025 MHz ARM | 500 MHz core | 400 MHz SDRAM | 6 overvolt'

			)

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $arm_freq_value MHz ARM | $core_freq_value MHz core | $sdram_freq_value MHz SDRAM | $over_voltage_value overvolt"; then

				TARGETMENUID=13 # Return to this menu

				case "$G_WHIP_RETURNED_VALUE" in

					'none') Reset_Overclocking;;

					'safe')

						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=2' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=900' /boot/config.txt

					;;

					'high')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=4' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=900' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

					'extreme')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=6' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1025' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

				esac

			fi

		# RPi 2
		elif (( $G_HW_MODEL == 2 )); then

			G_WHIP_MENU_ARRAY=(

				'none' ':  900 MHz ARM | 250 MHz core | 450 MHz SDRAM | 0 overvolt'
				'low' ': 1000 MHz ARM | 250 MHz core | 450 MHz SDRAM | 3 overvolt'
				'med' ': 1000 MHz ARM | 500 MHz core | 450 MHz SDRAM | 5 overvolt'
				'extreme' ': 1050 MHz ARM | 500 MHz core | 450 MHz SDRAM | 6 overvolt'

			)

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $arm_freq_value MHz ARM | $core_freq_value MHz core | $sdram_freq_value MHz SDRAM | $over_voltage_value overvolt"; then

				TARGETMENUID=13 # Return to this menu

				case "$G_WHIP_RETURNED_VALUE" in

					'none') Reset_Overclocking;;

					'low')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=3' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1000' /boot/config.txt

					;;

					'med')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=5' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1000' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

					'extreme')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=6' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1050' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

				esac

			fi

		# RPi 3/3+
		elif (( $G_HW_MODEL == 3 )); then

			# RPi 3+
			if [[ $G_HW_MODEL_NAME == *'+'* ]]; then

				G_WHIP_MENU_ARRAY=(

					'none' ': 1400 MHz ARM | 400 MHz core | 500 MHz SDRAM | 0 overvolt'
					'safe' ': 1450 MHz ARM | 400 MHz core | 500 MHz SDRAM | 0 overvolt'

				)

			# RPi 3
			else

				G_WHIP_MENU_ARRAY=(

					'none' ': 1200 MHz ARM | 400 MHz core | 450 MHz SDRAM | 0 overvolt'
					'low' ': 1300 MHz ARM | 400 MHz core | 450 MHz SDRAM | 3 overvolt'
					'med' ': 1325 MHz ARM | 400 MHz core | 450 MHz SDRAM | 4 overvolt'
					'high' ': 1350 MHz ARM | 400 MHz core | 450 MHz SDRAM | 5 overvolt'

				)

			fi

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $arm_freq_value MHz ARM | $core_freq_value MHz core | $sdram_freq_value MHz SDRAM | $over_voltage_value overvolt"; then

				TARGETMENUID=13 # Return to this menu

				case "$G_WHIP_RETURNED_VALUE" in

					'none') Reset_Overclocking;;

					'safe')

						Reset_Overclocking
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1450' /boot/config.txt

					;;

					'low')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=3' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1300' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=400' /boot/config.txt

					;;

					'med')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=4' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1325' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=400' /boot/config.txt

					;;

					'high')

						Warning_Overclocking || return
						Reset_Overclocking
						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=5' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1350' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=400' /boot/config.txt

					;;

				esac

			fi

		# RPi 4
		elif (( $G_HW_MODEL == 4 )); then

			G_WHIP_MENU_ARRAY=(

				'energy saving' ': 1500 MHz ARM | 500 MHz core | -2 overvolt'
				'default' ': 1500 MHz ARM | 500 MHz core | 0 overvolt'
				'safe' ': 1600 MHz ARM | 500 MHz core | 0 overvolt'
				'medium GPU' ': 1600 MHz ARM | 600 MHz core | 2 overvolt'
				'medium ARM' ': 1750 MHz ARM | 500 MHz core | 2 overvolt'
				'high GPU' ': 1750 MHz ARM | 600 MHz core | 4 overvolt'
				'high ARM' ': 1900 MHz ARM | 500 MHz core | 4 overvolt'

			)

			if G_WHIP_MENU "Hardware : $G_HW_MODEL_NAME\nCurrent: $arm_freq_value MHz ARM | $core_freq_value MHz core | $over_voltage_value overvolt"; then

				TARGETMENUID=13 # Return to this menu
				Reset_Overclocking

				case "$G_WHIP_RETURNED_VALUE" in

					'energy saving')

						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=-2' /boot/config.txt

					;;

					'safe')

						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1600' /boot/config.txt

					;;

					'medium GPU')

						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=2' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1600' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=600' /boot/config.txt

					;;

					'medium ARM')

						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=2' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1750' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

					'high GPU')

						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=4' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1750' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=600' /boot/config.txt

					;;

					'high ARM')

						G_CONFIG_INJECT 'over_voltage=' 'over_voltage=4' /boot/config.txt
						G_CONFIG_INJECT 'arm_freq=' 'arm_freq=1900' /boot/config.txt
						G_CONFIG_INJECT 'core_freq=' 'core_freq=500' /boot/config.txt

					;;

				esac

			fi

		fi

	}

	# TARGETMENUID=14
	Menu_AudioOptions(){

		TARGETMENUID=0

		if ! command -v aplay > /dev/null; then

			G_WHIP_MENU_ARRAY=('Enable' ': Install ALSA to enable audio capabilities')

		else

			local soundcard_current=$(sed -n '/^[[:blank:]]*CONFIG_SOUNDCARD=/{s/^[^=]*=//;p;q}' /boot/dietpi.txt)
			local plug_current='Off'
			[[ $soundcard_current =~ .*'-'(plug|eq)$ ]] && plug_current='On'
			G_WHIP_MENU_ARRAY=(
				'Sound card' ": [$soundcard_current]"
				'Auto-conversion' ": [$plug_current] Automatic software conversions"
				'DietPi-JustBoom' ': Launches EQ and MPD audio options menu'
			)

			# RPi, low power mode (PSU noise ripple reduction): https://github.com/MichaIng/DietPi/issues/757
			if (( $G_HW_MODEL < 10 )); then

				local psu_noise_reduction='Off'
				grep -q '^[[:blank:]]*CONFIG_CPU_GOVERNOR=powersave' /boot/dietpi.txt && grep -q '^[[:blank:]]*AUTO_SETUP_HEADLESS=1' /boot/dietpi.txt && psu_noise_reduction='On'
				G_WHIP_MENU_ARRAY+=('PSU noise reduction' ": [$psu_noise_reduction]")

			fi

			G_WHIP_MENU_ARRAY+=('' '●─' 'Disable' ': Disable all audio capabilities')

		fi

		G_WHIP_DEFAULT_ITEM='Sound card'
		if G_WHIP_MENU 'Please select an option:'; then

			TARGETMENUID=14 # Return to this menu

			if [[ $G_WHIP_RETURNED_VALUE == 'Disable' ]]; then

				/boot/dietpi/func/dietpi-set_hardware soundcard none
				G_AGP alsa-utils libasound2-plugin-equal firmware-intel-sound
				[[ -f '/boot/dietpi/.installed' ]] && G_CONFIG_INJECT 'aSOFTWARE_INSTALL_STATE\[5\]=' 'aSOFTWARE_INSTALL_STATE[5]=0' /boot/dietpi/.installed

			elif [[ $G_WHIP_RETURNED_VALUE == 'Enable' ]]; then

				G_AG_CHECK_INSTALL_PREREQ alsa-utils
				[[ -f '/boot/dietpi/.installed' ]] && G_CONFIG_INJECT 'aSOFTWARE_INSTALL_STATE\[5\]=' 'aSOFTWARE_INSTALL_STATE[5]=2' /boot/dietpi/.installed

			elif [[ $G_WHIP_RETURNED_VALUE == 'PSU noise reduction' ]]; then

				if [[ $psu_noise_reduction == 'Off' ]]; then

					G_WHIP_YESNO 'PSU noise reduction:\n\nThis mode attempts to reduce power consumption on your SBC. In turn, this may reduce PSU inflicted noise, that may degrade audio output quality.
\nThe following will now be applied:\n - CPU governor = powersave\n - Display output = disabled\n\nDo you want to continue?' || return

					G_CONFIG_INJECT 'CONFIG_CPU_GOVERNOR=' 'CONFIG_CPU_GOVERNOR=powersave' /boot/dietpi.txt
					/boot/dietpi/func/dietpi-set_cpu
					/boot/dietpi/func/dietpi-set_hardware headless 1
					tvservice -o

				else

					G_CONFIG_INJECT 'CONFIG_CPU_GOVERNOR=' 'CONFIG_CPU_GOVERNOR=schedutil' /boot/dietpi.txt
					/boot/dietpi/func/dietpi-set_cpu
					/boot/dietpi/func/dietpi-set_hardware headless 0
					tvservice -p

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'Sound card' ]]; then

				G_WHIP_MENU_ARRAY=()

				# RPi, all but rpi-bcm2835 disables
				if (( $G_HW_MODEL < 10 )); then

					G_WHIP_MENU_ARRAY+=('rpi-bcm2835-auto' ': Onboard: HDMI if plugged in, else 3.5mm')
					G_WHIP_MENU_ARRAY+=('rpi-bcm2835-3.5mm' ': Onboard: 3.5mm forced output')
					G_WHIP_MENU_ARRAY+=('rpi-bcm2835-hdmi' ': Onboard: HDMI forced output')
					G_WHIP_MENU_ARRAY+=('allo-boss-dac-pcm512x-audio' ': Allo Boss DAC')
					G_WHIP_MENU_ARRAY+=('allo-boss2-dac-audio' ': Allo Boss2 DAC')
					G_WHIP_MENU_ARRAY+=('allo-digione' ': Allo DigiOne')
					G_WHIP_MENU_ARRAY+=('allo-katana-dac-audio' ': Allo Katana DAC')
					G_WHIP_MENU_ARRAY+=('allo-piano-dac-pcm512x-audio' ': Allo Piano DAC')
					G_WHIP_MENU_ARRAY+=('allo-piano-dac-plus-pcm512x-audio' ': Allo Piano DAC 2.1')
					G_WHIP_MENU_ARRAY+=('applepi-dac' ': ApplePi DAC (Orchard Audio)')
					G_WHIP_MENU_ARRAY+=('dionaudio-loco' ': Dion Audio LOCO')
					G_WHIP_MENU_ARRAY+=('dionaudio-loco-v2' ': Dion Audio LOCO V2')
					G_WHIP_MENU_ARRAY+=('googlevoicehat-soundcard' ': Google AIY voice kit')
					G_WHIP_MENU_ARRAY+=('hifiberry-amp' ': HifiBerry AMP / AMP+')
					G_WHIP_MENU_ARRAY+=('hifiberry-dac' ': HifiBerry DAC / MiniAMP')
					G_WHIP_MENU_ARRAY+=('hifiberry-dacplus' ': HifiBerry DAC+ / DAC+ Pro / AMP2')
					G_WHIP_MENU_ARRAY+=('hifiberry-dacplusadc' ': HifiBerry DAC+ADC')
					G_WHIP_MENU_ARRAY+=('hifiberry-dacplusadcpro' ': HifiBerry DAC+ADC Pro')
					G_WHIP_MENU_ARRAY+=('hifiberry-dacplusdsp' ': HifiBerry DAC+DSP')
					G_WHIP_MENU_ARRAY+=('hifiberry-dacplushd' ': HifiBerry DAC+ HD')
					G_WHIP_MENU_ARRAY+=('hifiberry-digi' ': HifiBerry Digi / Digi+')
					G_WHIP_MENU_ARRAY+=('hifiberry-digi-pro' ': HifiBerry Digi+ Pro')
					G_WHIP_MENU_ARRAY+=('i-sabre-q2m' ': AudioPhonics I-Sabre ES9028Q2M / ES9038Q2M')
					G_WHIP_MENU_ARRAY+=('iqaudio-codec' ': IQaudIO Pi-Codec HAT')
					G_WHIP_MENU_ARRAY+=('iqaudio-dac' ': IQaudIO DAC audio card')
					G_WHIP_MENU_ARRAY+=('iqaudio-dacplus' ': Pi-DAC+, Pi-DACZero, Pi-DAC+ Pro, Pi-DigiAMP+')
					G_WHIP_MENU_ARRAY+=('iqaudio-digi-wm8804-audio' ': Pi-Digi+')
					G_WHIP_MENU_ARRAY+=('iqaudio-dacplus,auto_mute_amp' ': Pi-DigiAMP+')
					G_WHIP_MENU_ARRAY+=('iqaudio-dacplus,unmute_amp' ': Pi-DigiAMP+')
					G_WHIP_MENU_ARRAY+=('justboom-dac' ': JustBoom: DAC HAT, Amp HAT, DAC Zero and Amp Zero')
					G_WHIP_MENU_ARRAY+=('justboom-digi' ': JustBoom: Digi HAT and Digi Zero')
					G_WHIP_MENU_ARRAY+=('justboom-both' ': JustBoom: Simultaneous DAC and Digi usage')
					G_WHIP_MENU_ARRAY+=('rpi-dac' ': Soekris DAM1021 (pcm1794a)')

				# C2
				elif (( $G_HW_MODEL == 12 )); then

					G_WHIP_MENU_ARRAY+=('default' ': HDMI')
					G_WHIP_MENU_ARRAY+=('odroid-hifishield-plus' ': Odroid HiFi Shield 1/Plus')
					G_WHIP_MENU_ARRAY+=('odroid-hifishield-2' ': Odroid HiFi Shield 2')

				# NanoPi M2/M3
				elif [[ $G_HW_MODEL == 6[12] ]]; then

					G_WHIP_MENU_ARRAY+=('default' ': 3.5mm Analogue')
					G_WHIP_MENU_ARRAY+=('s5pxx18-hdmi' ': HDMI')

				# H3
				elif (( $G_HW_CPUID == 1 )); then

					G_WHIP_MENU_ARRAY+=('default' ': HDMI')
					G_WHIP_MENU_ARRAY+=('H3-analogue' ': 3.5mm Analogue')

				# Sparky SBC
				elif (( $G_HW_MODEL == 70 )); then

					G_WHIP_MENU_ARRAY+=('default' ': HDMI')
					G_WHIP_MENU_ARRAY+=('snd-soc-allo-piano-dac' ': Allo Piano DAC')
					G_WHIP_MENU_ARRAY+=('snd-soc-allo-piano-dac-plus' ': Allo Piano DAC 2.1')
					G_WHIP_MENU_ARRAY+=('allo-cheapo-analogue' ': Allo Cheapo (3.5mm / RCA output)')
					G_WHIP_MENU_ARRAY+=('allo-cheapo-optical' ': Allo Cheapo (Optical output)')
					G_WHIP_MENU_ARRAY+=('usb-dac-1.1' ': USB 1.1 Audio DAC (any)')

				# ASUS TB
				elif (( $G_HW_MODEL == 52 )); then

					G_WHIP_MENU_ARRAY+=('default' ': HDMI')
					G_WHIP_MENU_ARRAY+=('asus-tb-analogue' ': 3.5mm Analogue')

				fi

				# Intel SST DSP
				grep -qi 'vendor_id.*intel' /proc/cpuinfo && G_WHIP_MENU_ARRAY+=('intel-sst-dsp' ': Intel SST DSP firmware')

				# Global usb-dac, prefer at bottom of list
				G_WHIP_MENU_ARRAY+=('' '●─ Auto detection' 'usb-dac' ': USB Audio DAC (any)')

				for i in {0..9}
				do
					[[ -f /proc/asound/card$i/id ]] || continue

					for j in {0..9}
					do
						[[ -f /proc/asound/card$i/pcm${j}p/info ]] || continue

						local card_name=$(<"/proc/asound/card$i/id")
						card_name+=$(sed -n '/^name:/{s/^name://p;q}' "/proc/asound/card$i/pcm${j}p/info")
						G_WHIP_MENU_ARRAY+=("hw:$i,$j" ": $card_name")
					done
				done

				G_WHIP_DEFAULT_ITEM=$soundcard_current
				G_WHIP_MENU "Please select a soundcard\n - Current : $soundcard_current" || return
				/boot/dietpi/func/dietpi-set_hardware soundcard "$G_WHIP_RETURNED_VALUE"

				# RPi: Reboot required to apply device tree changes, which applies to all but auto-detected selections
				(( $G_HW_MODEL > 9 )) || [[ $G_WHIP_RETURNED_VALUE == 'hw:'[0-9]','[0-9] || $G_WHIP_RETURNED_VALUE == 'usb-dac' ]] || REBOOT_REQUIRED=1

				# RPi: When Allo Boss2 DAC was selected, offer to enable OLED display right now
				if [[ $G_WHIP_RETURNED_VALUE == 'allo-boss2-dac-audio' ]]
				then
					G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO 'Do you want to enable the OLED display on the Allo Boss2 case?
\nThis can be done or disabled at any later time via:
- "dietpi-config" > "Display Options" > "LCD/OLED Panel addon"' && /boot/dietpi/func/dietpi-set_hardware lcdpanel 'allo-boss2-oled'
				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'Auto-conversion' ]]; then

				# Remove equalizer and plug suffix
				local soundcard_target=${soundcard_current%-eq}
				soundcard_target=${soundcard_target%-plug}
				if [[ $plug_current == 'Off' ]]; then

					/boot/dietpi/func/dietpi-set_hardware soundcard "$soundcard_target-plug"

				else

					/boot/dietpi/func/dietpi-set_hardware soundcard "$soundcard_target"

				fi

			elif [[ $G_WHIP_RETURNED_VALUE == 'DietPi-JustBoom' ]]; then

				/boot/dietpi/misc/dietpi-justboom

			fi

		fi

	}

	# TARGETMENUID=15
	STRESS_TEST_MODE=0 # 0=CPU only | 1=CPU/RAM 2=CPU/RAM/IO
	STRESS_TEST_DURATION=60
	STRESS_TEST_RESULTS_TEMP_MIN=0
	STRESS_TEST_RESULTS_TEMP_MAX=0

	Menu_StressTest(){

		TARGETMENUID=11

		local stress_test_mode_text='CPU Burn: (CPU only)'
		if (( $STRESS_TEST_MODE == 1 )); then

			stress_test_mode_text='CPU & RAM: (CPU, RAM)'

		elif (( $STRESS_TEST_MODE == 2 )); then

			stress_test_mode_text='Full: (CPU, DISK, RAM)'

		fi

		G_WHIP_MENU_ARRAY=(

			'Mode' ": [$stress_test_mode_text]"
			'Duration' ": [$(( $STRESS_TEST_DURATION / 60 )) Minutes]"
			'Start' ': Launch the stress test'

		)

		if G_WHIP_MENU 'Please select an option:'; then

			TARGETMENUID=15 # Return to this menu

			if [[ $G_WHIP_RETURNED_VALUE == 'Duration' ]]; then

				G_WHIP_MENU_ARRAY=(

					'60' ': 1 Minute'
					'300' ': 5 Minutes'
					'1800' ': 30 Minutes'
					'3600' ': 1 Hour'
					'21600' ': 6 Hours (Winter months?)'

				)

				G_WHIP_DEFAULT_ITEM=$STRESS_TEST_DURATION
				G_WHIP_MENU 'Please select a duration for the test' && STRESS_TEST_DURATION=$G_WHIP_RETURNED_VALUE

			elif [[ $G_WHIP_RETURNED_VALUE == 'Mode' ]]; then

				G_WHIP_MENU_ARRAY=(

					'0' ': CPU Burn: (CPU only)'
					'1' ': CPU & RAM: (CPU, RAM)'
					'2' ': Full: (CPU, DISK, RAM)'

				)

				G_WHIP_DEFAULT_ITEM=$STRESS_TEST_MODE
				G_WHIP_MENU 'Please select a stress test type' && STRESS_TEST_MODE=$G_WHIP_RETURNED_VALUE

			elif [[ $G_WHIP_RETURNED_VALUE == 'Start' ]]; then

				G_AG_CHECK_INSTALL_PREREQ stress || exit 1

				G_DIETPI-NOTIFY 3 Stress_Test "Running stress test for $STRESS_TEST_DURATION seconds"
				G_DIETPI-NOTIFY 2 'To terminate, type: killall -w stress'

				local start_time=$(date)
				local start_time_epoch=$(date +%s)
				local memory_per_thread=$(( $(free -m | mawk '/^Mem:/ {print $2;exit}') / ( $G_HW_CPU_CORES * 2 ) ))
				local fp_log='/root/dietpi-config_stress.log'
				[[ -f $fp_log ]] && rm $fp_log

				if (( $STRESS_TEST_MODE == 0 )); then

					stress -c $(( $G_HW_CPU_CORES * 2 )) -t "$STRESS_TEST_DURATION"s &

				elif (( $STRESS_TEST_MODE == 1 )); then

					stress -c $(( $G_HW_CPU_CORES * 2 )) -i "$G_HW_CPU_CORES" -m "$G_HW_CPU_CORES" --vm-bytes "$memory_per_thread"M -t "$STRESS_TEST_DURATION"s &

				elif (( $STRESS_TEST_MODE == 2 )); then

					stress -c $(( $G_HW_CPU_CORES * 2 )) -i "$G_HW_CPU_CORES" -m "$G_HW_CPU_CORES" --vm-bytes "$memory_per_thread"M -d 2 -t "$STRESS_TEST_DURATION"s &

				fi

				# Reset
				STRESS_TEST_RESULTS_TEMP_MIN=1000
				STRESS_TEST_RESULTS_TEMP_MAX=0

				# Check if system supports temp readouts
				local cpu_supports_temp=0
				local cpu_temp=$(G_OBTAIN_CPU_TEMP)
				disable_error=1 G_CHECK_VALIDINT "$cpu_temp" && cpu_supports_temp=1

				# Loop until stress completed
				local remaning_time=0
				while pgrep 'stress' &> /dev/null
				do
					cpu_temp=$(G_OBTAIN_CPU_TEMP)
					remaning_time=$(( $STRESS_TEST_DURATION + ( $start_time_epoch - $(date +%s) ) ))

					echo -e "$(date) | $cpu_temp'c | $remaning_time seconds remaining"
					echo -e "$(date) | $cpu_temp'c" >> "$fp_log"

					if (( $cpu_supports_temp )); then

						(( $cpu_temp > $STRESS_TEST_RESULTS_TEMP_MAX )) && STRESS_TEST_RESULTS_TEMP_MAX=$cpu_temp
						(( $cpu_temp < $STRESS_TEST_RESULTS_TEMP_MIN )) && STRESS_TEST_RESULTS_TEMP_MIN=$cpu_temp

					fi

					sleep 1
					((time_since_start++))
				done

				local end_time=$(date)
				local end_time_epoch=$(date +%s)
				local duration_seconds=$(( $end_time_epoch - $start_time_epoch ))

				local output_string=" - Start Time: $start_time
 - End Time  : $end_time
 - Duration  : $duration_seconds seconds
 - Min Temp  : $STRESS_TEST_RESULTS_TEMP_MIN 'c
 - Max Temp  : $STRESS_TEST_RESULTS_TEMP_MAX 'c
 - log       : $fp_log"

				G_DIETPI-NOTIFY 0 'Stress Test Completed'
				G_DIETPI-NOTIFY 2 "$output_string"

				G_WHIP_MSG "Stress test results:\n$output_string"

			fi

		fi

	}

	# TARGETMENUID=16
	Menu_Network_Nas_Misc(){

		TARGETMENUID=0

		# APT mirror
		local apt_mirror_current=$(grep -m1 '^[[:blank:]]*deb[[:blank:]]' /etc/apt/sources.list | mawk '{print $2}')
		[[ $apt_mirror_current ]] || apt_mirror_current='Unknown, no string from scrape'

		# NTP mirror
		local ntp_mirror_current=$(sed -n '/^[[:blank:]]*CONFIG_NTP_MIRROR=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		[[ $ntp_mirror_current ]] || ntp_mirror_current='Unknown, no string from scrape'

		# Network boot wait
		local boot_wait_for_network=$(sed -n '/^[[:blank:]]*CONFIG_BOOT_WAIT_FOR_NETWORK=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		local boot_wait_for_network_text='10 Seconds MAX (default)'
		if [[ $boot_wait_for_network == 0 ]]; then

			boot_wait_for_network_text='Off'

		elif [[ $boot_wait_for_network == 2 ]]; then

			boot_wait_for_network_text='Infinite wait'

		fi

		local check_url_timeout=$(sed -n '/^[[:blank:]]*CONFIG_G_CHECK_URL_TIMEOUT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		disable_error=1 G_CHECK_VALIDINT "$check_url_timeout" 0 || check_url_timeout=10
		local check_url_attempts=$(sed -n '/^[[:blank:]]*CONFIG_G_CHECK_URL_ATTEMPTS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
		disable_error=1 G_CHECK_VALIDINT "$check_url_attempts" 1 || check_url_attempts=2

		G_WHIP_MENU_ARRAY=(

			'' '●─ Mirror Options '
			'APT Mirror' ": [$apt_mirror_current]"
			'NTP Mirror' ": [$ntp_mirror_current]"
			'' '●─ Connection Test Options '
			'Boot Net Wait' ": [$boot_wait_for_network_text]"
			'G_CHECK_URL Timeout' ": [$check_url_timeout Seconds]"
			'G_CHECK_URL Attempts' ": [$check_url_attempts Tries]"
			'' '●─ Additional Options '
			'Network Drives' ': Mount/control network storage'
			'Dynamic DNS' ': Manage domains for your dynamic IP'

		)

		if G_WHIP_MENU; then

			TARGETMENUID=16 # Return to this menu

			case "$G_WHIP_RETURNED_VALUE" in

				'G_CHECK_URL Timeout')

					local min=0 max=60
					G_WHIP_DEFAULT_ITEM=$check_url_timeout
					if G_WHIP_INPUTBOX "This setting tells DietPi how long to wait, before DietPi-internal connection and URL checks assume a dead connection attempt (and failure).\nIncrease this value if you have a 'flaky' connection.\n
Please enter a value in seconds between $min and $max. \"0\" means unlimited, however this is not recommended to avoid unlimited background job hang." && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $min $max; then

						G_CONFIG_INJECT 'CONFIG_G_CHECK_URL_TIMEOUT=' "CONFIG_G_CHECK_URL_TIMEOUT=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt

					fi

				;;

				'G_CHECK_URL Attempts')

					local min=1 max=10
					G_WHIP_DEFAULT_ITEM=$check_url_attempts
					if G_WHIP_INPUTBOX "This setting tells DietPi how many times to test a connection or URL, before assuming a dead connection or URL link (and failure).\nIncrease this value if you have a 'flaky' connection.\n
Please enter a value between $min and $max." && G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" $min $max; then

						G_CONFIG_INJECT 'CONFIG_G_CHECK_URL_ATTEMPTS=' "CONFIG_G_CHECK_URL_ATTEMPTS=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt

					fi

				;;

				'Network Drives')

					G_WHIP_YESNO 'The ability to mount and control networked drives has moved to:\n - DietPi-Drive_manager\n\nWould you like to launch the program now?' && /boot/dietpi/dietpi-drive_manager

				;;

				'Boot Net Wait')

					G_WHIP_MENU_ARRAY=(

						'0' ': Disabled'
						'1' ': Wait 10 Seconds MAX for network, before continuing boot (default)'
						'2' ': Infinite wait for network, before continuing boot'

					)

					G_WHIP_DEFAULT_ITEM=$boot_wait_for_network
					G_WHIP_MENU 'The following options will allow you to delay boot, until a valid network connection is available:' && G_CONFIG_INJECT 'CONFIG_BOOT_WAIT_FOR_NETWORK=' "CONFIG_BOOT_WAIT_FOR_NETWORK=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt

				;;

				'APT Mirror')

					local failure=
					while :
					do
						# Create Menu List for Whiptail
						G_WHIP_MENU_ARRAY=('Custom' ': Manually enter APT mirror')

						# - Raspbian
						if (( $G_HW_MODEL < 10 )) && (( $G_RASPBIAN )); then

							local mirror_list='https://www.raspbian.org/RaspbianMirrors/'
							G_WHIP_MENU_ARRAY+=('http://raspbian.raspberrypi.org/raspbian/' ': Global mirror director (default)')
							G_WHIP_MENU_ARRAY+=('https://mirror.ox.ac.uk/sites/archive.raspbian.org/archive/raspbian/' ': UK')
							G_WHIP_MENU_ARRAY+=('https://mirror.netcologne.de/raspbian/raspbian/' ': Germany')
							G_WHIP_MENU_ARRAY+=('https://mirror.umd.edu/raspbian/raspbian/' ': USA')
							G_WHIP_MENU_ARRAY+=('https://mirrors.ustc.edu.cn/raspbian/raspbian/' ': China')
							G_WHIP_MENU_ARRAY+=('http://raspbian.mirror.digitalpacific.com.au/raspbian/' ': Australia')

						# - Debian
						else

							local mirror_list='https://www.debian.org/mirror/list'
							G_WHIP_MENU_ARRAY+=('https://deb.debian.org/debian/' ': Global mirror director (default)')
							G_WHIP_MENU_ARRAY+=('https://ftp.debian.org/debian/' ': Global')
							G_WHIP_MENU_ARRAY+=('http://ftp.uk.debian.org/debian/' ': UK')
							G_WHIP_MENU_ARRAY+=('http://ftp.de.debian.org/debian/' ': Germany')
							G_WHIP_MENU_ARRAY+=('http://ftp.us.debian.org/debian/' ': USA')
							G_WHIP_MENU_ARRAY+=('http://ftp.cn.debian.org/debian/' ': China')
							G_WHIP_MENU_ARRAY+=('http://ftp.au.debian.org/debian/' ': Australia')

						fi

						G_WHIP_DEFAULT_ITEM=$apt_mirror_current
						G_WHIP_MENU "${failure}Please select an APT mirror, or choose custom for manual entry.\nA list of available mirrors can be found at: $mirror_list" || break

						if [[ $G_WHIP_RETURNED_VALUE == 'Custom' ]]; then

							G_WHIP_DEFAULT_ITEM=$apt_mirror_current
							G_WHIP_INPUTBOX 'Please enter a new APT mirror, e.g. http://ftp.debian.org/debian/' || continue

						fi

						/boot/dietpi/func/dietpi-set_software apt-mirror "$G_WHIP_RETURNED_VALUE" || { failure='[FAILED] An internal error occurred, please report this issue to:\n - https://github.com/MichaIng/DietPi/issues\n\n'; continue; }
						apt_mirror_current=$G_WHIP_RETURNED_VALUE
						G_EXEC_NOHALT=1 G_AGUP && break || failure='[FAILED] APT update failed, please try another APT mirror.\n\n'
					done

				;;

				'NTP Mirror')

					# Create Menu List for Whiptail
					G_WHIP_MENU_ARRAY=(

						'Gateway' ': Use local router as NTP server (Recommended)'
						'Custom' ': Manually enter NTP mirror'
						'Default' ': Fallback to system defaults'
						'' '●─ Continental NTP pools '
						'europe.pool.ntp.org' ': Europe'
						'north-america.pool.ntp.org' ': North America'
						'south-america.pool.ntp.org' ': South America'
						'africa.pool.ntp.org' ': Africa'
						'asia.pool.ntp.org' ': Asia'
						'oceania.pool.ntp.org' ': Oceania'
						'' '●─ Global NTP pools '
						'debian.pool.ntp.org' ': Debian Global'
						'pool.ntp.org' ': Global'

					)

					G_WHIP_DEFAULT_ITEM=$ntp_mirror_current
					if G_WHIP_MENU 'Please select an NTP mirror:\n
"Gateway": Try to detect and use local router for time sync. Recommended, allows fastest sync and reduces load to the *.pool.ntp.org servers.\n
"Custom": Manually enter local or external NTP server address(es).\n
"Default": Leave mirror choice to system. Usually falls back to local gateway (Stretch+ only) or "debian.pool.ntp.org".\n
Use "*.pool.ntp.org" mirrors, if your device is mobile or should act as local NTP server. Further information: "http://www.pool.ntp.org/zone/@"' && [[ $G_WHIP_RETURNED_VALUE ]]; then

						case $G_WHIP_RETURNED_VALUE in

							'Custom')

								G_WHIP_DEFAULT_ITEM=$ntp_mirror_current
								G_WHIP_INPUTBOX 'Please enter one or more (space-separated) NTP mirrors.\n
NB: If you need to use *.pool.ntp.org servers, enter the base domain only. The subdomains 0-3 will be added automatically.
- Enter "uk.pool.ntp.org" to use [0-3].uk.pool.ntp.org' || return

							;;

						esac

						G_CONFIG_INJECT 'CONFIG_NTP_MIRROR=' "CONFIG_NTP_MIRROR=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
						/boot/dietpi/func/dietpi-set_software ntpd-mode "$(sed -n '/^[[:blank:]]*CONFIG_NTP_MODE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)"
						# Run time sync only, if not currently running, to avoid concurrent execution if dietpi-config was called from DietPi-Run_NTPD error handler
						# - Run non-interactively to avoid its internal error handler allowing to open a concurrent dietpi-config instance
						pgrep -cif /dietpi/func/run_ntpd &> /dev/null && return
						if ! G_INTERACTIVE=0 MAX_LOOPS_CHECK=10 /boot/dietpi/func/run_ntpd 1; then

							G_WHIP_MSG "Time sync failed:\n - $G_WHIP_RETURNED_VALUE\n\nSetting reverted to previous."
							G_CONFIG_INJECT 'CONFIG_NTP_MIRROR=' "CONFIG_NTP_MIRROR=$ntp_mirror_current" /boot/dietpi.txt
							/boot/dietpi/func/dietpi-set_software ntpd-mode "$(sed -n '/^[[:blank:]]*CONFIG_NTP_MODE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)"

						fi

					fi

				;;

				'Dynamic DNS') /boot/dietpi/dietpi-ddns;;

			esac

		# Cancel
		else

			# Exit DietPi-Config on back to previous menu?
			if (( $EXITONBACK == 1 )); then

				TARGETMENUID=16 # Return to this menu
				Menu_Exit

			fi

		fi

	}

	PROXY_ENABLED=0
	PROXY_ADDRESS=
	PROXY_PORT=
	PROXY_USERNAME=
	PROXY_PASSWORD=

	# So we can call this in other menus (eg: submenu of this)
	Load_Proxy_Vars(){

		# Satisfy shellcheck
		[[ $http_proxy ]] || http_proxy=

		if [[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]]; then

			PROXY_ENABLED=1
			. /etc/bashrc.d/dietpi-proxy.sh

		else

			PROXY_ENABLED=0
			# Inform user if DietPi proxy state does not match variable existence
			# - This occurs either because of missing reboot/login after exiting script before, or, proxy was set up outside of DietPi scripts
			# - Prompt only when inside/entering proxy settings
			[[ $http_proxy && $TARGETMENUID == 17 ]] && G_WHIP_MSG 'Either a proxy was set up outside of DietPi scripts or you need to reload you current login session (logout+login or reboot) for changes to take effect.'

		fi

		if [[ $http_proxy ]]; then

			PROXY_ADDRESS=${http_proxy#*//}; PROXY_ADDRESS=${PROXY_ADDRESS%:*}
			PROXY_PORT=${http_proxy##*:}
			[[ $http_proxy == *'@'* ]] || return
			PROXY_ADDRESS=${PROXY_ADDRESS#*@}
			PROXY_USERNAME=${http_proxy#*//}; PROXY_USERNAME=${PROXY_USERNAME%%:*}
			PROXY_PASSWORD=${http_proxy%%@*}; PROXY_PASSWORD=${PROXY_PASSWORD##*:}

		else

			[[ $PROXY_ADDRESS ]] || PROXY_ADDRESS=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_ADDRESS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			[[ $PROXY_PORT ]] || PROXY_PORT=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PORT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			[[ $PROXY_USERNAME ]] || PROXY_USERNAME=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
			[[ $PROXY_PASSWORD ]] || PROXY_PASSWORD=$(sed -n '/^[[:blank:]]*CONFIG_PROXY_PASSWORD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)

		fi

	}

	# TARGETMENUID=17
	Menu_NetworkAdapters_Proxy(){

		Load_Proxy_Vars

		local proxy_state_text='Off'
		(( $PROXY_ENABLED )) && proxy_state_text='On'

		G_WHIP_MENU_ARRAY=(

			'State' ": [$proxy_state_text]"
			'Address' ": [$PROXY_ADDRESS]"
			'Port' ": [$PROXY_PORT]"
			'Username' ": [$PROXY_USERNAME]"
			'Password' ": [$PROXY_PASSWORD]"

		)

		if G_WHIP_MENU 'Please select an option to change:'; then

			case "$G_WHIP_RETURNED_VALUE" in

				'State')

					(( $PROXY_ENABLED )) && PROXY_ENABLED=0 || PROXY_ENABLED=1

				;;

				'Address')

					G_WHIP_DEFAULT_ITEM=$PROXY_ADDRESS
					G_WHIP_INPUTBOX 'Please enter the proxy URL or IP address\n - eg: MyProxy.com' && PROXY_ADDRESS=$G_WHIP_RETURNED_VALUE
					G_CONFIG_INJECT 'CONFIG_PROXY_ADDRESS=' "CONFIG_PROXY_ADDRESS=$PROXY_ADDRESS" /boot/dietpi.txt

				;;

				'Port')

					G_WHIP_DEFAULT_ITEM=$PROXY_PORT
					G_WHIP_INPUTBOX 'Please enter the proxy port number\n - eg: 1234' && PROXY_PORT=$G_WHIP_RETURNED_VALUE
					G_CONFIG_INJECT 'CONFIG_PROXY_PORT=' "CONFIG_PROXY_PORT=$PROXY_PORT" /boot/dietpi.txt

				;;

				'Username')

					G_WHIP_DEFAULT_ITEM=$PROXY_USERNAME
					G_WHIP_INPUTBOX 'Please enter the proxy username\n - eg: JoeBloggs\n - Leave blank if not required' && PROXY_USERNAME=$G_WHIP_RETURNED_VALUE
					G_CONFIG_INJECT 'CONFIG_PROXY_USERNAME=' "CONFIG_PROXY_USERNAME=$PROXY_USERNAME" /boot/dietpi.txt

				;;

				'Password')

					G_WHIP_DEFAULT_ITEM=$PROXY_PASSWORD
					G_WHIP_INPUTBOX 'Please enter the proxy password\n - eg: LetMeIn\n - Leave blank if not required' && PROXY_PASSWORD=$G_WHIP_RETURNED_VALUE
					G_CONFIG_INJECT 'CONFIG_PROXY_PASSWORD=' "CONFIG_PROXY_PASSWORD=$PROXY_PASSWORD" /boot/dietpi.txt

				;;

			esac

			# Add export settings
			if (( $PROXY_ENABLED )); then

				if [[ $PROXY_USERNAME && $PROXY_PASSWORD ]]; then

					echo "export {http,https,ftp}_proxy='http://$PROXY_USERNAME:$PROXY_PASSWORD@$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh

				else

					echo "export {http,https,ftp}_proxy='http://$PROXY_ADDRESS:$PROXY_PORT'" > /etc/bashrc.d/dietpi-proxy.sh

				fi

			else

				[[ -f '/etc/bashrc.d/dietpi-proxy.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-proxy.sh
				unset -v {http,https,ftp}_proxy # Has no effect on current login session but for this script, e.g. connection test

			fi

			REBOOT_REQUIRED=1

		else

			TARGETMENUID=8 # Return to Network Adapters menu

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Main Loop
	#/////////////////////////////////////////////////////////////////////////////////////
	if (( $G_DIETPI_INSTALL_STAGE >= 0 )); then

		# Start DietPi-Config
		until (( $TARGETMENUID < 0 ))
		do
			G_TERM_CLEAR
			G_WHIP_BUTTON_CANCEL_TEXT=$TEXT_MENU_BACK

			if (( $TARGETMENUID == 0 )); then

				G_WHIP_BUTTON_CANCEL_TEXT='Exit'
				Menu_Main

			elif (( $TARGETMENUID == 1 )); then

				Menu_DisplayOptions

			elif (( $TARGETMENUID == 2 )); then

				Menu_DisplayOptions_Driver_Resolution

			elif (( $TARGETMENUID == 3 )); then

				Menu_AdvancedOptions

			elif (( $TARGETMENUID == 4 )); then

				Menu_PerformanceOptions

			elif (( $TARGETMENUID == 5 )); then

				Menu_SecurityOptions

			elif (( $TARGETMENUID == 6 )); then

				Menu_GpumemoryOptions

			elif (( $TARGETMENUID == 7 )); then

				Menu_LanguageOptions

			elif (( $TARGETMENUID == 8 )); then

				Menu_NetworkAdapters

			elif (( $TARGETMENUID == 9 )); then

				Menu_NetworkAdapters_Ethernet

			elif (( $TARGETMENUID == 10 )); then

				Menu_NetworkAdapters_Wifi

			elif (( $TARGETMENUID == 11 )); then

				Menu_Tools

			elif (( $TARGETMENUID == 12 )); then

				Menu_FilesystemBenchmark

			elif (( $TARGETMENUID == 13 )); then

				Menu_Overclock

			elif (( $TARGETMENUID == 14 )); then

				Menu_AudioOptions

			elif (( $TARGETMENUID == 15 )); then

				Menu_StressTest

			elif (( $TARGETMENUID == 16 )); then

				Menu_Network_Nas_Misc

			elif (( $TARGETMENUID == 17 )); then

				Menu_NetworkAdapters_Proxy

			elif (( $TARGETMENUID == 18 )); then

				Menu_AdvancedOptions_Serial_UART

			elif (( $TARGETMENUID == 19 )); then

				Menu_AdvancedOptions_APT

			else

				G_WHIP_MSG "[FAILED] Unknown menu ID $TARGETMENUID, reverting to DietPi-Config main menu
\nThis error should never show up. Please try to reproduce it. If it reappears, you found a coding bug.
Please report it to: https://github.com/MichaIng/DietPi/issues"
				TARGETMENUID=0

			fi
		done

	else

		G_WHIP_MSG '[ INFO ] First run setup has not reached sufficient state.\n\nPlease reboot before using DietPi-Config. If the issue persists, please report this as bug.'

	fi

	#-----------------------------------------------------------------------------------
	exit
	#-----------------------------------------------------------------------------------
}
